. est le produit scalaire
* est la multiplication d'un vecteur par un réel
Soit un rayon passant par O(ox,oy,oz), de direction le vecteur unitaire D(dx,dy,dz)
Soit une sphère de centre (a,b,c) et de rayon r
Nous recherchons l'intersection I(x,y,z) Il existe 2 méthodes :
Nous avons le système : (x-a)^2 + (y-b)^2 + (z-c)^2 = r^2 x=ox + t*dx y=oy + t*dy z=oz + t*dz avec le vecteur D(dx,dy,dz) de norme 1 Soit : (ox+t*dx - a)^2 + (oy+t*dy - b)^2 + (oz+t*dz - c)^2 = r^2 t^2(dx^2+dy^2+dz^2) + t*2( dx(ox-a)+dy(oy-b)+dz(oz-c) ) + (ox-a)^2+(oy-b)^2+(oz-c)^2-r^2 = 0 D'oû A*t^2 + B*t + C=0 Avec : A = dx^2+dy^2+dz^2=1 car norme de D=1 B = 2( dx(ox-a)+dy(oy-b)+dz(oz-c) ) C = (ox-a)^2+(oy-b)^2+(oz-c)^2-r^2 det = B^2-4AC = B^2-4C Si det>=0 alors il y a une/deux intersection(s) sqdet = sqrt(det) t1 = (-b-sqdet)/2 t2 = (-b+sqdet)/2 si t1<0 alors t1=t2 si t2<0 alors t2=t1 t = min(t1,t2) P(x,y,z) = O(ox,oy,oz) + t*D(dx,dy,dz)
-> |D | = 1 -> -> OK = D . OC CK^2 = OC^2-OK^2 Si 0<CK^2<=r^2 alors il y a intersection -> -> OI = D*(ok-sqrt(r^2 - CK^2))
Soit un rayon passant par O(ox,oy,oz), de direction le vecteur unitaire D(dx,dy,dz), et le triangle ABC. N est la normale unitaire du triangle.
![]() |
-> -> OO' = OA . N -> -> OI = OO'/acos( (OO' . D)/OO' ) -> -> OI = OI * D |
Soit O la caméra, D la direction du rayon de norme 1, et ABC un triangle.
Avec la méthode précédente, on trouve l'intersection I entre le rayon et le plan (ABC).
On veut maintenant vérifier si l'intersection est à l'intérieur du triangle.
Pour cela on précalcule A', B', C' les bases des hauteurs du triangles, et G le barycentre.
![]() |
L'intersection est dans le triangle si :-> -> A'I . A'G >= 0 -> -> et B'I . B'G >= 0 -> -> et C'I . C'G >= 0 |
Cette méthode fonctionne avec n'importe quel polygone et risque d'être plus rapide que la méthode précédente dans le cas de triangles.
Soient A(1),...,A(n) les différents points du polygones.
Pour tous les triangles I,A(i),A(i+1), calculons l'aire algébrique de chaque triangle :
![]() |
-> -> -> Aire*2 = N . ( IA(i) * IA(i+1) ) -> -> -> Aire*2 = N . vecteur_constantSi toutes les aires sont de même signe, l'intersection est dans le polygone. |
La nouvelle direction est : -> -> -> -> -> R = D - 2 ( D . N) * D Il ne reste plus qu'a tracer un nouveau rayon depuis P de direction R
Calculez un buffer de poly_id : pour chaque pixel, indiquez quel polygone/primitive est affiché(e) et quelle couleur est extraite de la texture - en calculant un sbuffer par exemple. Puis lancez un rayon sur le bon polygone seulement pour chaque pixel.
Ou alors, utilisez un quadtree.
1---2---1---2---1---2---1 |.......|.......|.......| |.......|.......|.......| |.......|.......|.......| 2...2...2...2...2...2...2 |.......|.......|.......| |.......|.......|.......| |.......|.......|.......| 1---2---1---2---1---2---1
Calculez une cullbox 2D (un carré englobant la sphère à l'écran:
C'est juste un produit de Thales, x2d = focale*X/Z et y2d = focale*Y/Z. avec -1.0<= x2d ou y2d <= +1.0.
Changez de repère pour avoir des coordonnées en pixels et votre cullbox est prête.
Puis vérifiez avant de lancer un rayon sur une sphère si le pixel actuel est dans la cullbox de la sphère.
-> |D| = 1 -> -> OK = D . OC CK^2 = OC*OC-OK*OKSi CK^2 <= rayon*rayon, le rayon touche la sphère.
Utilisez une structure comme les arbres BSP (sous leur forme générique, ou de grille - octree, grille avec poids...), l'encapsulation de plusieurs objets proches dans des sphères... pour accélérer la détection de l'objet touché
Main page | email : Sly |