Archive for the ‘maths’ Category
librairie GLua
GLua est une librairie open source qui offre au programmeurs LUA des classes et functions qui singent celles disponibles en GLSL, le « OpenGL Shading Language ».
GLua a été spécialement conçue comme librairie de base pour Demoniak3D, pour fournir un ensemble cohérent avec les shaders GLSL.
Contenu:
- vec3.lua : vecteurs et arithmétique 3D
- mat3.lua : matrice et arithmétique 3D
- vec4.lua : vecteurs et arithmétique 3D
- glsl.lua : fonctions génériques suivant les prototypes glsl comme définis dans le livre « OpenGL Shading Language » by Randi J. Rost
- test.X.lua : tests unitaires du module X
Utilisation et exemples:
L’utilisation des classes et fonctions est relativement simple.
Regardez les fichiers test.X.lua pour plus de détails et d’exemples.
Téléchargement:
GLua est disponible sur http://luaforge.net/projects/glua/ sous licence LGPL.
Détails d’implémentation:
- les classes sont basées sur class.lua, décrite ici: http://lua-users.org/wiki/SimpleLuaClasses
- glsl.lua offre des fonctions génériques fonctionnant sur les nombres et tables LUA, et donc avec toutes les classes matrice/vecteur. Elle utilise intensivement la « programmation fonctionnelle » pour ce faire:
- la fonction « apply » est définie comme suit:
--- applies a function to a table of parameters
-- @param f : function to apply to each element in v
-- @param v : (vector of) parameter(s) to f function
-- @return : (vector of) result(s) of f(v)
function apply(f,v)
if type(v)=="number" then return f(v) end
if type(v)=="table" then
local res={}
for i,x in ipairs(v) do res[i]=f(x) end
return res
end
error("apply "..f.."("..type(v)..") not implemented")
end - ainsi, les fonctions peuvent facilement être définies pour accepter des nombres, vecteurs et tables:
function sin(rad)
return apply(math.sin,rad)
end
- la fonction « apply » est définie comme suit:
- le produit scalaire est implanté de 2 manières distinctes :
- dans l’opérateur « exposant » ^ des classes
- comme fonction générique dot(p1,p2) dans glsl.lua
GLua library
GLua is an open source library which provides LUA programmers with classes and functions that mimic those available in GLSL, the OpenGL Shading Language.
GLua was especially designed as a base library for the Demoniak3D real-time engine, as it provides a consistent framework with GLSL shaders.
Contents:
- vec3.lua : 3D vectors and arithmetic
- mat3.lua : 3D matrix and arithmetic
- vec4.lua : 4D vectors and arithmetic
- glsl.lua : generic functions following glsl prototypes as defined in book « OpenGL Shading Language » by Randi J. Rost
- test.X.lua : unit test of module X
Usage & Samples:
Usage of the classes and functions is pretty straightforward.
Check the test.X.lua modules for more details or examples
Download:
GLua is available on http://luaforge.net/projects/glua/ under LGPL licence.
Implementation details:
- the classes are based on class.lua, described on http://lua-users.org/wiki/SimpleLuaClasses
- glsl.lua offers generic function that work on LUA numbers and tables, and therefore all vector / matrix classes. It makes extensive use of functional programming to achieve this:
- the « apply » function is defined as follows:
--- applies a function to a table of parameters
-- @param f : function to apply to each element in v
-- @param v : (vector of) parameter(s) to f function
-- @return : (vector of) result(s) of f(v)
function apply(f,v)
if type(v)=="number" then return f(v) end
if type(v)=="table" then
local res={}
for i,x in ipairs(v) do res[i]=f(x) end
return res
end
error("apply "..f.."("..type(v)..") not implemented")
end - then, functions can easily be defined to support numbers, vectors, or matrices:
function sin(rad)
return apply(math.sin,rad)
end
- the « apply » function is defined as follows:
- dot product is implemented in 2 different ways :
- through the « power » ^ operator in classes
- as a generic dot(p1,p2) function in glsl.lua
Ensembles de Julia calculés en temps réel par GPU
Retrouvé par hasard un travail très intéressant de Keenan Crane (dont on a déjà parlé ici) datant de 2005 sur cette page et dans cet article. Il s’agit d’un véritable tutoriel sur le ray-tracing en temps réel d’un objet mathématique particulier, l’ensemble de Julia, le tout calculé sur un GPU. Comme le dit Keenan, il y a deux problèmes avec l’ensemble de Julia:
- il prend des siècles à calculer
- il est totalement inutile
mais il est très beau, comme on le voit sur ces captures :
En fait, l’ensemble de Julia est un objet à 4 dimensions que l’on visualise par « tranche en 3 dimensions ». En coupant une tranche en 2 dimensions dans une direction particulière, on obtient d’ailleurs l’ensemble de Mandelbrot plus connu, que Demoniak3D calcule sur GPU de façon spectaculaire.
Un exécutable avec son code source sont disponible sur la page « Ray Tracing Quaternion Julia Sets on the GPU » de Keenan Crane. Il utilise
- d’une part un petit bout de code C basé sur GLUT pour implanter la méthode décrite dans l’article « Ray Tracing Deterministic 3-D Fractals » de John Hart
- d’autre part un fragment en Cg pour les calculs de l’ensemble de Julia.
Le problème, c’est que ce dernier code n’a plus l’air de fonctionner avec le tout récent Cg 2.0… Avant que je m’attaque à porter tout ceci en GLSL + LUa sur Demoniak 3D, est-ce que quelqu’un qui connait le Cg pourrait me dire ce qui cloche, voire corriger la version actuelle ?
l’interpolation sphérique linéaire
L’orientation d’un corps dans l’espace à 3 dimension est défini par 3 angles tout comme la position d’un objet posé sur une sphère est définie par les 2 angles de latitude et de longitude, plus un angle définissant l’orientation de l’objet
Le problème consistant à faire tourner « en douceur » un objet dans l’espace pour l’amener dans une orientation déterminée est appelé « interpolation sphérique linéaire » parce qu’il est équivalent à celui consistant à se déplacer « en douceur » sur une sphère pour atteindre une position et une orientation donnée. Le problème n’est pas trivial pour 2 raisons:
- comme les angles sont définis « modulo 360° », il faut que l’interpolation en tienne compte : si on va par exemple de la longitude -179° à la longitude +179°, il faut faire 2° dans le sens négatif et pas 358° dans le sens positif.
- quelle que soit la manière dont on définit les 3 angles, il existe des « singularités » aux point analogues aux pôles : à la lattitude 90°, la longitude n’a plus d’importance mais si on passe par le pôle, il faut « se rappeler » de notre dernière longitude pour pouvoir continuer « tout droit » dans la longitude augmentée de 180° (modulo 360°), et simultanément éviter qu’une mauvaise description de l’angle d’orientation nous fasse faire brusquement un demi-tout sur nous mêmes en passant par le pôle pour conserver un angle par rapport au nord …
La page « the right way to calculate stuff » dont je parle aussi ici décrit la fonction « slerp » [1] qui définit l’interpolation sphérique linéaire entre 2 vecteurs unitaires v0, v1 ainsi:
sin((1-t)*a) sin(t*a)
slerp(v0,v1,t) = ______________*v0 + __________*v1 sin(a) sin(a)
où a est l’angle entre v0 et v1 (calculé comme indiqué ici). Mais il est clair que pour des angles tels que sin(a) est nul ou très petit, des problèmes numériques vont survenir. En travaillant un peu la fonction slerp peut s’écrire:
sin_over_x((1-t)*a) sin_over_x(t*a) slerp(v0,v1,t) = ____________________*(1-t)*v0 + ________________*t*v1 sin_over_x(a) sin_over_x(a)
où sin_over_x est la fonction sin(x)/x calculée de façon robuste, toujours comme indiqué ici.
Reste à traiter le cas ou a est proche de 180°, ce qui revient à retourner un objet, ou à aller aux antipodes du point où on se trouve sur le globe. Il y a alors une infinité de trajets possibles, et il faut bien en choisir un plutôt que de laisser l’ordinateur se planter…
Références:
- Ken Shoemake, Animating rotation with quaternion curves, SIGGraph ’85 proceedings