accueil Companime / accueil Immersion / console comPanrama / logiciels  détail du calcul 


accès au source
(cette page utilise la police "greek.ttf" pour afficher les caractères grecs)

Projection sur un cube : classe CPanCamera
Obtention de 5 images en perspective classique en gardant ces images en mémoire, sans les afficher.
Dans la convention OpenGL, par défaut la caméra est centrée à l'origine et regarde du coté des Z négatifs.
La caméra reste centrée à l'origine, mais se trouve successivement dirigée vers :
- image 0 : les Z négatifs                -> texture 0
- image 1 : les X négatifs, (rotY +90°)   -> texture 1  (partie droite)
- image 2 : les Y négatifs, (rotX -90°)   -> texture 2  (partie inférieure)
- image 3 : les X positifs, (rotY -90°)   -> texture 1  (partie droite)
- image 4 : les Y positifs. (rotX +90°)   -> texture 2  (partie supérieure)
Ceci est ma convention. Apparemment chacun fait à sa guise dans ce domaine.
La caméra a une ouverture de 90° horizontalement et verticalement.

Seule la face 0 est entière. Les cotés ne sont que des demi-faces.
On utilise la fonction glFrustum qui permet de filmer une demi-face.

L'extension FBO (Frame Buffer Object) permet d'enregistrer les images comme texture
sans les afficher (sans les envoyer dans le "Frame Buffer").

[voir dans le source le module PanCamera.cpp et la fonction CPanCamera::shot() ]<
>

application des textures : classe CMesh
On passe des images-faces-du-cube à l'image finale en considérant les faces comme des textures que l'on applique sur l'image finale au moyen de maillages.
- un maillage départ appliqué sur les textures (maillage lineaire).
- un maillage destination appliqué sur l'image finale (maillage fisheye ou maillage miroir).

[ pour en savoir plus, voir les fichiers sources PanCamera.cpp PanCamera.h Mesh.cpp et Mesh.h ]
la caméra-cube "ouverte"
numérotation des faces et du maillage
le maillage-miroir

Ces maillages sont en 5 parties correspondant aux 5 faces du cube.
Ils sont regroupés sur 3 textures.
Chaque maillage est un tableau à une dimension dans lequel les 5 parties sont enregistrées à la suite, comme le montre le schéma ci-contre.
Il y a aussi un tableau d'indices qui permet à openGL d'appliquer ces maillages de manière efficace.
[ voir dans la classe CMesh les fonctions build_linear(), build_indices() et display()]
configuration des textures
maillage "linear"
maillage miror
(le maillage "fisheye" est analogue)


Un point C d'une face du cube est représenté par ses coordonnées textures (s,t),    s et t variant de 0 à 1 (imposé par OpenGL).
Mais le point C a aussi des coordonnées spatiales x, y et z telles que, pour chaque face :
 face 0   x = 2s-1   y = 2t-1   z =   -1  front
 face 1   x =   -1   y = 2t-1   z = 1-2s  left 
 face 2   x = 2s-1   y =   -1   z = 1-2t  bottom
 face 3   x =    1   y = 2t-1   z = 2s-1  right
 face 4   x = 2s-1   y =    1   z = 2t-1  top 
 
Le point C a pour image le point q situé sur la sphère unité inscrite dans le cube :
Si L est la distance du centre de la sphère unité au point C situé sur la face, on a :
L  =  racine carrée (x2+ y2 + z2)
xq = x/L       
yq = y/L       
zq = z/L

[ voir dans la classe CMesh les fonctions build_fisheye() et build_miror() ]
 

Système avec fisheye
Calcul du chemin inverse : fonction CMesh::xyz_fisheye_uv()
Si le système est centré (l'optique et la coupole ont le même axe) le calcul est simple.
(Dans le cas contraire (que je n'ai pas étudié), on est proche d'un système avec miroir).

(x,y,z sont les coordonnées d'un point C situé sur le cube caméra)
(u,v sont les coordonnées du point c correspondant dans l'image projecteur)
Trois étapes :
- calcul de l'angle Q entre le plan horizontal (ox,oz) et le plan passant par C et oz.
- calcul de l'angle a entre oz et oC.
- module du point c.
En fait on "déroule" la demi-sphère sur le plan tangent.
[ pour en savoir plus, voir le source Mesh.cpp et Mesh.h ]
    

Système avec miroir

On change d'abord de référentiel
Nous avons besoin de deux systèmes de référentiels :

1) le premier zy (minuscules) sert à définir la configuration physique de la console.
Il est utilisé pour communiquer cette configuration au logiciel comPanConfig.
Des trois éléments composant la console : coupole, miroir, projecteur,
la coupole, à cause de sa taille, est le plus stable
les réglages se font en déplaçant le miroir ou le projecteur).
On prend donc comme origine le centre de la coupole.

L'axe y est vertical,
l'axe z est orienté dans le sens projecteur->miroir.
(ceci est cohérent avec OpenGL).

Les coordonnées du miroir sont donc zM et yM (yM est negatifs sur la figure)
Celles du projecteur zP et yP (tous deux negatifs sur la figure)
La coupole est inclinée d'un angle (gamma) (environ -45° sur la figure)
2) le second ZY (majuscules) est le référentiel interne de calcul.
On a besoin de le connaître seulement pour comprendre le source des logiciels.

L'origine est prise au centre du miroir M.
L'axe Z passe par le projecteur.
Il est dirigé encore dans le sens projecteur->miroir.
L'axe X est horizontal, dirigé vers nous.

Ce référentiel est incliné d'un angle  (alpha) par rapport au précédent.
(environ -20° sur la figure)

On applique un facteur d'échelle qui rend le rayon du miroir égal à 1.
L'échelle n'a, en fait, aucune importance car le maillage résultant sera d'abord
normalisé en (O,1), puis ajusté à la définition de l'image (1280 dans mon cas).


passage du point c sur la phère unité au point Q sur le dome : fonction CMesh::xyz_miror_uv()
[ voir le source Mesh.cpp et Mesh.h ]

calcul du chemin inverse : fonction CMesh::q_miror_uv()

   

Considérons le plan ZY' qui contient les points M, P, Q et I (il fait un angle w avec le plan vertical ZY) :
on calcule l'angle f tel que I soit le point de reflexion du rayon issu de P et touchant la coupole en Q.
Le principe de Fermat disant que la lumière emprunte le chemin le plus court, f sera tel que la somme des distances QI+IP sera minimum.

Dans ce plan les coordonnées de Q sont (MH=Qz, HQ)

celle de P est Pz   (Py==0)
celles de I sont cos(f) et sin(f)   (le rayon du miroir étant égal à 1)

le segment IQ a pour composantes Qz - cos(f) et Qy - sin(f)
le segment IP a pour composantes Pz - cos(f) et -sin(f)


La difficulté du calcul se ramène à déterminer f pour que l'expression :
          soit minimale.


On ne sait pas calculer directement une telle expression.
Il faut faire appel à une technique d'approximations successives.

(Heureusement il y a toujours quelque internaute de bonne volonté qui met son travail à disposition et fait gagner beaucoup de temps).

Ce calcul est relativement lent. Mais on ne calcule les grilles qu'une seule fois.

En résumé, le point Q, situé sur la coupole,
est l'image du point c (sur l'image, dans le projecteur),
après réflection sur le miroir sphérique en I.
Les coordonnées du point c dans l'image sont (u,v).

[ pour en savoir plus, voir le source Mesh.cpp et Mesh.h ]