IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Réordonner les sommets d'un polygon 3D en sens horaire (ou anti-horaire)


Sujet :

C

  1. #1
    Membre régulier
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Avril 2011
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2011
    Messages : 108
    Points : 98
    Points
    98
    Par défaut Réordonner les sommets d'un polygon 3D en sens horaire (ou anti-horaire)
    Je voudrais pouvoir réordonner les indices des sommets utilisés par un polygone 3D afin que ceux-ci respectent un ordre horaire
    (ou anti-horaire, pas bien important, le principal est que l'ordre de ces sommets soit correct afin de produire à coup sûr un polygon convexe)

    Aucun problème pour le faire en 2D, il suffit de calculer un segment de référence V1 entre le millieu et un des sommets, de lister les angles entre ce segment et l'ensemble des autres segments V2 allant du millieu du polygone vers chacun des sommets, de réordonner cette liste en ordre croissant des angles, puis enfin de réindexer en fonction les sommets utilisés par ce polygone

    Mais par contre, je ne retrouve aucune source C permettant de faire cela en 3D, bien que quasiment sûr que ça doive exister

    Ci-joint, le code que j'utilise pour réordonner correctement les sommets d'un polygone afin qu'ils soient listés dans le sens horaire mais ça ne semble marcher qu'avec des polygones inclus dans le plan XY, cf. en 2D et non pas en 3D ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h> 
     
    #define MAX_GONE 	10
    #define MAX_POLYGONS 	100
     
    typedef struct _v3f
    {
    	float x, y, z;
    } v3f;
     
    typedef struct _polygon
    {
    	int poly;
     
    	int gone[MAX_GONE];
     
    } polygon;
     
    typedef struct _reindexed
    {
    	int v;
    	float angle;
    } indexed;
     
      v3f QuadVertices[4] = // quad with incorrect vertices ordering (non manifold)
    { 
    	{ -1.0f,  0.0f, 0.0f }, 
    	{  1.0f,  0.0f, 0.0f }, 
    	{  0.0f,  1.0f, 0.0f }, 
    	{  0.0f, -1.0f, 0.0f } 
    };
     
     
    v3f center;
    v3f v1;
    v3f v2;
     
    indexed Indexed[4];
     
    polygon Faces[MAX_POLYGONS];
     
    void MakeQuadConnectivity()
    {
    	Faces[0].poly = 4;
    	Faces[0].gone[0] = 0;
    	Faces[0].gone[1] = 1;
    	Faces[0].gone[2] = 2;
    	Faces[0].gone[3] = 3;
    }
     
     
    void PrintVertices( v3f *v, int num )
    {
    	int i;
     
    	for ( i = 0 ; i < num ; i++ )
    	{
    		printf("v[%d] = { %.0f , %.0f , %.0f } \n", 
    			i, 
    			v[i].x, 
    			v[i].y, 
    			v[i].z
    	 	); 
    	}
    }
     
     
    float Normalize( v3f *v )
    {
    	float dist1, dist2 = 0.0f;
     
    	dist2 += v->x * v->x;
    	dist2 += v->y * v->y;
    	dist2 += v->z * v->z;
     
    	dist1 = 1.0f / sqrt( dist2 );
     
    	v->x *= dist1;
    	v->y *= dist1;
    	v->z *= dist1;
    } 
     
     
    void ComputeAngles(v3f *v, int num, indexed *Idx)
    {
    	int i;
     
    	float cosinus, signe, angle;
     
     
    	for ( i = 0 ; i < num ; i++)
    	{
    		center.x += v[i].x;
    		center.y += v[i].y;
    		center.z += v[i].z;
    	}
     
    	center.x /= num;
    	center.y /= num;
    	center.z /= num;
     
    	v1.x = v[0].x - center.x;
    	v1.y = v[0].y - center.y;
    	v1.z = v[0].z - center.z; 
     
    	Normalize(&v1); 
    	// printf("v1 = {*%.0f, %.0f, %.0f } \n", v1.x, v1.y, v1.z); 
     
     
    	for ( i = 0; i < num ; i++)
    	{
    		v2.x = v[i].x - center.x;
    		v2.y = v[i].y - center.y;
    		v2.z = v[i].z - center.z;
    		Normalize(&v2); 
     
     
    		cosinus = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
     
    		angle = acos(cosinus) * (180.0f / M_PI);
     
    		signe = v1.x * v2.y - v1.y * v2.x;
     
     
    		if ( signe < 0.0f )
    		{
    			angle += 180.0f;
    		}
     
     
    		Idx[i].v = i;
    		Idx[i].angle = angle;
     
    		// printf("Angle[%d] = %.0f \n", i, angle);
    	}  	
    }
     
    int Reindexation( const void *a, const void *b )
    {
    	indexed *pa, *pb;
     
    	pa = (indexed *) a;
    	pb = (indexed *) b;
     
    	return pa->angle - pb->angle;   
    }
     
     
    void PrintReindexed( v3f *v, int num, indexed *Idx, polygon *p )
    {
    	int i;
     
    	qsort( Idx, num, sizeof(indexed), Reindexation);
     
    	if ( p )  p->poly = num;
     
    	for ( i = 0 ; i < num ; i++ )
    	{
    		printf("v[%d -> %d] = {%.0f, %.0f, %.0f } [angle=%.0f] \n",
    			Idx[i].v, 
    			i,
    			v[ Idx[i].v ].x,
    			v[ Idx[i].v ].y,
    			v[ Idx[i].v ].z,
    			Idx[i].angle
    		);
     
    		if ( p ) p->gone[i] = Idx[i].v; 
    	}
    } 
     
    void PrintPolygon( polygon * p)
    {
    	int i;
     
    	printf("\nPolygon[%d] = [ ", p->poly);
     
    	for ( i = 0 ; i < p->poly ; i++ )
    	{
    		printf("%d ", p->gone[i] );
    	}
    	printf(" ] \n");
    }
     
     
     
     
     
    int main( int argc , char **argv )
    {
    	MakeQuadConnectivity();
     
    	printf("Avant reindexation \n");
    	PrintVertices(QuadVertices, 4);
     
    	printf("\nRéindexation ...\n\n");
    	ComputeAngles(QuadVertices, 4, Indexed);
     
    	PrintReindexed(QuadVertices, 4, Indexed, &Faces[0] );
     
    	PrintPolygon( &Faces[0] );
     
    	return 0;
    }
    Ce qui renvoie cela qui marche bien avec des polygones 2D mais ne fonctionne pas correctement avec des polygones 3D non inclus dans le plan XY

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    Avant reindexation 
    v[0] = {-1 , 0 , 0 } 
    v[1] = {1 , 0 , 0 } 
    v[2] = {0 , 1 , 0 } 
    v[3] = {0 , -1 , 0 } 
     
    Réindexation ...
     
    v[0 -> 0] = {-1, 0, 0 } [angle=0] 
    v[3 -> 1] = {0, -1, 0 } [angle=90] 
    v[1 -> 2] = {1, 0, 0 } [angle=180] 
    v[2 -> 3] = {0, 1, 0 } [angle=270] 
     
    Polygon[4] = [ 0 3 1 2  ]
    Je pense que tout le problème doit être dans cette partie qui ne semble fonctionner que dans le plan XY, du moins pour le calcul du signe ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
                    cosinus = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
     
    		angle = acos(cosinus) * (180.0f / M_PI);
     
    		signe = v1.x * v2.y - v1.y * v2.x;
     
     
    		if ( signe < 0.0f )
    		{
    			angle += 180.0f;
    		}

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 197
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 197
    Points : 17 169
    Points
    17 169
    Par défaut
    As-tu une définition mathématique de l'ordre total 3D que tu veux faire?
    Autrement-dit, en 3D, le sens horaire se fait par rapport à quelle direction et dans quel sens?

    Si ton polygone est plan, ca peut encore se faire par transformation de coordonnées: tu définis les axes x et y du plan du polygone, tu transpose ses sommets dans ces coordonnées, et tu appliques ton algo 2D.
    Mais si ton polygone n'est pas plat, ton ordre doit être plus général.

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 754
    Points : 31 097
    Points
    31 097
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par yannoo95170 Voir le message
    Ci-joint, le code que j'utilise pour réordonner correctement les sommets d'un polygone afin qu'ils soient listés dans le sens horaire mais ça ne semble marcher qu'avec des polygones inclus dans le plan XY, cf. en 2D et non pas en 3D ...
    Je n'arrive pas bien à visualiser ce que doit représenter un polygone 3D avec les sommets ordonnés dans un sens horaire. Le sens horaire s'applique à une forme 2D (typiquement un cadran de montre à aiguille). Mais en 3D ça donne quoi?
    Prenons pr exemple une pyramide égyptienne. Il y a donc un sommet en haut (A), puis les 3 sommets de la base (B, C et D). Ordonner ces quatre sommets dans le sens horaire ça donne quoi??? D'autant plus que j'ai présenté cette pyramide selon une orientation "arbitraire" (similaire à une vraie pyramide posée sur le sol) mais dans la réalité, elle peut-être orientée n'importe comment sans que cela ne change sa nature de pyramide...

  4. #4
    Membre régulier
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Avril 2011
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2011
    Messages : 108
    Points : 98
    Points
    98
    Par défaut
    Tous les points du polygone sont bien sûr contenus sur le même plan, ce sont des polygones "plans", pas des pyramides

    Pour le sens, aucune importance que ce dans le sens horaire ou anti-horaire, le but est d'obtenir à coup sûr des polygones convexes, cf. surtout pas de polygones **NON** convexes
    (comme fait dans mon code en 2D via le "signe = v1.x * v2.y - v1.y * v2.x;" et le "if ( signe < 0.0f ){ angle += 180.0f; }" + le tri avec les angles classés dans l'ordre croissant ensuite, sauf que c'est sa version en 3D que je voudrais avoir, cf. calcul du signe en 3D plutôt qu'en 2D )

    A noter que le "signe = v1.x * v2.y - v1.y * v2.x;" est la composante Z du produit vectoriel entre V1 et V2
    => il me faudrait la même chose mais qui gère et assemble les composantes X, Y et Z "en même temps"

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 754
    Points : 31 097
    Points
    31 097
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par yannoo95170 Voir le message
    Tous les points du polygone sont bien sûr contenu sur un plan, ce sont des polygones "plans", pas des pyramides
    Dans ce cas, à quoi sert la 3° dimension ?

    Citation Envoyé par yannoo95170 Voir le message
    Pour le sens, aucune importance que ce dans le sens horaire ou anti-horaire, le but est d'obtenir à coup sûr des polygones convexes, cf. surtout pas de polygones **NON** convexes
    Rien ne garantit cela. Même un polygône avec tous ses sommets qui suivent dans l'ordre le cadran d'une montre peut parfaitement être "non" convexe...
    Nom : 440px-Simple_polygon.svg.png
Affichages : 131
Taille : 8,9 Ko

  6. #6
    Membre régulier
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Avril 2011
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2011
    Messages : 108
    Points : 98
    Points
    98
    Par défaut
    Ark, pas glop du tout ça

    A quoi sert la troisième dimension ?
    => bein pour pouvoir y gérer des polygones en 3D, pas seulement en 2D

    A noter que les polygones qui me seront donnés en entrée seront déjà convexes, c'est seulement le bon ordre des sommets qui n'est pas garanti et qu'il me faut réordonner

    En fait, ce seront des fans, cf. un contour dans un même plan dont il me faudra réordonner les sommets dans le bon ordre

    Dans cet exemple, l'ordre donné des sommets en entrée serait 0, 1,3,2,4,5,7,6 et il me faudrait les réordonner en sortie comme cette image en 0,1,2,3,4,5,6,7

    Nom : fans.jpeg
Affichages : 118
Taille : 6,7 Ko

    Mais je crois voir la "ruse"
    => il va me falloir pivoter/"faire tourner en 3D" chacun des polygones/fans sur le plan XY, cf. que leurs normales soient sur l'axe des Z, afin de pouvoir y extraire l'ordre correct ?

  7. #7
    Membre régulier
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Avril 2011
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2011
    Messages : 108
    Points : 98
    Points
    98
    Par défaut
    Plus précisément, ce seront des pyramides telles que celle-ci, sauf que l'apex sera toujours au centre du "cercle", jamais au dessus ou en dessous
    => des pyramides plates = polygones plats convexes quoi
    (la base de Axis et Apex auront exactement les mêmes coordonnées, cf. celles du centre du "cercle" => la hauteur de la pyramide sera donc de 0 )

    Nom : ApexAxis.png
Affichages : 111
Taille : 4,9 Ko

  8. #8
    Membre régulier
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Avril 2011
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2011
    Messages : 108
    Points : 98
    Points
    98
    Par défaut
    Pour test, je viens d'essayer en changeant le calcul 2D "signe = v1.x * v2.y - v1.y * v2.x" par un calcul 3D "signe = (v1.y * v2.z - v1.z * v2.y) * ( v1.x * v2.z - v1.z * v2.x) * (v1.x * v2.y - v1.y * v2.x);", cf. par la multiplication des composantes X, Y et Z du produit vectoriel de v1 et v2

    => bein ça ne marche pas
    (assez logique : il suffit qu'une seule des composantes X, Y ou Z soit à 0 pour le signe deviennent lui aussi systématiquement à 0 car 0 * qqchose * qquchosedautre = toujours 0 ...)

    ==> quelque part, ça aurait été trop facile ... mais ça valait quand même le coup d'être essayé : on ne sait jamais, il arrive parfois des miracles

  9. #9
    Membre régulier
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Avril 2011
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2011
    Messages : 108
    Points : 98
    Points
    98
    Par défaut
    Je viens d'avoir une autre idée, je vais calculer la boîte englobante 3D des sommets et en extraire l'axe X, Y ou Z qui a la plus petite d'amplitude

    a) si le plus petit axe d'amplitude est X, je ferais le calcul de signe sur le plan X, donc avec les coordonnées y et z de V1 et V2

    b) si le plus petit axe d'amplitude est Y, je ferais le calcul de signe sur le plan Y, donc avec les coordonnées x et z de V1 et V2

    c) si le plus petit axe d'amplitude est Z je ferais le calcul de signe sur le plan Z, donc avec les coordonnées x et y de V1 et V2

    Le cas c) est celui qui est utilisé avec l'algorithme original "2D only", cf. "signe = v1.x * v2.y - v1.y * v2.x;" car l'amplitude de variation des coordonnnées sur l'axe Z est obligatoirement la plus petite car tous les z sont égaux à 0 donc amplitude de variation des coordonnées sur Z = 0 = variation minimale possible ...)

    L'idée de faire le calcul sur le plus petit axe d'amplitude m'est venu en fouinant sur le net à propos de l'ACP car je recherche en fait les 2 axes les plus importants du polygone afin d'effectuer le calcul sur l'axe le moins important = celui qui reste , et que je me rappelle avoir déjà vu ce genre de trucs pour accélérer des calculs de ray-tracing, des calculs de visibilité ou autres constructions d'arbres BSP / quadtree / octree

    => je fouine encore un peu sur le Net pour essayer de voir si les quaternions ne seraient pas une autre piste intéressante à explorer et vous tiens au courant de mon pèlerinage dans le monde du réordonnancement des sommets d'un polygone 3D dont les sommets ont été données dans un ordre quelquonque

  10. #10
    Membre régulier
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Avril 2011
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2011
    Messages : 108
    Points : 98
    Points
    98
    Par défaut
    L'idée du calcul de la boîte englobante du polygone 3D pour extraire l'axe d'extraction de l'angle semble fonctionner

    J'ai "seulement" dû changer le code de la fonction ComputeAngles() , et ajouté quelques polygones 3D de test pour tester quelques cas de figures
    (pas encore essayé avec l'axe minimum Y à la place de l'axe X ou Z mais ça devrait sûrement marcher de même)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
     
    #include "facets.h"
     
     
    v3f QuadVertices0[4] = // quad with incorrect vertices ordering (non manifold) on XY
    { 
    	{ -1.0f,  0.0f, 0.0f }, 
    	{  1.0f,  0.0f, 0.0f }, 
    	{  0.0f,  1.0f, 0.0f }, 
    	{  0.0f, -1.0f, 0.0f } 
    };
     
    v3f QuadVertices1[4] = // another quad with incorrect vertices ordering (non manifold) on YZ
    { 
    	{ 0.0f, -1.0f,  0.0f }, 
    	{ 0.0f,  1.0f,  0.0f }, 
    	{ 0.0f,  0.0f,  1.0f }, 
    	{ 0.0f,  0.0f, -1.0f } 
    };
     
    v3f QuadVertices2[4] =  // another quad with **correct** vertices ordering (manifold) on XY
    {
    	{ 0.0f , 0.0f, 0.0f },
    	{ 1.0f , 0.0f, 0.0f },
    	{ 1.0f , 1.0f, 0.0f },
    	{ 0.0f , 1.0f, 0.0f }
    };
     
    v3f QuadVertices3[4] =  // another quad with incorrect vertices ordering (non manifold) on YZ
    {
    	{ 0.0f, 0.0f , 0.0f },
    	{ 0.0f, 1.0f , 1.0f },
    	{ 0.0f, 1.0f , 0.0f },
    	{ 0.0f, 0.0f , 1.0f }
    };
     
    v3f *QuadVertices = QuadVertices3; 
     
     
    v3f center;
    v3f v1;
    v3f v2;
     
    indexed Indexed[4];
     
    polygon Faces[MAX_POLYGONS];
     
    void MakeQuadConnectivity()
    {
    	Faces[0].poly = 4;
    	Faces[0].gone[0] = 0;
    	Faces[0].gone[1] = 1;
    	Faces[0].gone[2] = 2;
    	Faces[0].gone[3] = 3;
    }
     
     
    void PrintVertices( v3f *v, int num )
    {
    	int i;
     
    	for ( i = 0 ; i < num ; i++ )
    	{
    		printf("v[%d] = {*%.0f , %.0f , %.0f } \n", 
    			i, 
    			v[i].x, 
    			v[i].y, 
    			v[i].z
    	 	); 
    	}
    }
     
     
    float Normalize( v3f *v )
    {
    	float dist1, dist2 = 0.0f;
     
    	dist2 += v->x * v->x;
    	dist2 += v->y * v->y;
    	dist2 += v->z * v->z;
     
    	dist1 = 1.0f / sqrt( dist2 );
     
    	v->x *= dist1;
    	v->y *= dist1;
    	v->z *= dist1;
    } 
     
     
    void ComputeAngles(v3f *v, int num, indexed *Idx)
    {
    	int i;
     
    	float cosinus, signe, angle;
    	v3f mini, maxi;
    	float aX, aY, aZ;
    	int axe = 2; // axe Z par défaut
     
     
    	// calcul du centre du polygone
    	for ( i = 0 ; i < num ; i++)
    	{
    		center.x += v[i].x;
    		center.y += v[i].y;
    		center.z += v[i].z;
    	}
     
    	center.x /= num;
    	center.y /= num;
    	center.z /= num;
     
    	// calcul du vecteur V1 (vecteur normalisé allant du centre vers le premier sommet du polygone) 
    	v1.x = v[0].x - center.x;
    	v1.y = v[0].y - center.y;
    	v1.z = v[0].z - center.z; 
    	Normalize(&v1); 
    	// printf("v1 = {*%.0f, %.0f, %.0f } \n", v1.x, v1.y, v1.z); 
     
     
    	// calcul de la boîte englobante 
    	mini.x = v[0].x;
    	mini.y = v[0].y;
    	mini.z = v[0].z;
     
    	maxi.x = v[0].x;
    	maxi.y = v[0].y;
    	maxi.z = v[0].z;
     
    	for ( i = 1 ; i < num; i++ )
    	{
    		if ( v[i].x < mini.x ) mini.x = v[i].x;
    		if ( v[i].y < mini.y ) mini.y = v[i].y; 
    		if ( v[i].z < mini.z ) mini.z = v[i].z; 
     
    		if ( v[i].x > maxi.x ) maxi.x = v[i].x; 
    		if ( v[i].y > maxi.y ) maxi.y = v[i].y; 
    		if ( v[i].z > maxi.z ) maxi.z = v[i].z;  
    	}
     
    	aX = maxi.x - mini.x;
    	aY = maxi.y - mini.y;
    	aZ = maxi.z - mini.z;
     
     
    	// Extraction de l'axe minimal (axe Z = 2 par défaut) 
    	if ( aX < aZ )
    	{
    		// l'axe Z ne peut être l'axe minimum, tester entre l'axe X et l'axe Y
    		if ( aX < aY )
    		{
    			// axe X minimum
    			axe = 0;
    		}
    		else if ( aY < aZ )
    		{
    			// axe Y minimum
    			axe = 1;
    		}
    	}
    	else 
    	{
    		// l'axe Z est peut-être l'axe minimum, tester si l'axe Y est pas encore plus petit 
    		if ( aY < aZ )
    		{
    			// axe Y minimum
    			axe = 1;
    		}
    	}
     
     
    	// calcul de l'angle entre le vecteur V1 et le vecteur normalisé allant du centre vers chacun des sommets V2
    	for ( i = 0; i < num ; i++)
    	{
    		v2.x = v[i].x - center.x;
    		v2.y = v[i].y - center.y;
    		v2.z = v[i].z - center.z;
    		Normalize(&v2); 
     
     
    		// calcul du cosinus de l'angle  entre V1 et V2 = produit scalaire V1*V2
    		cosinus = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
     
    		// calcul de l'angle "non dirigé" à partir de son cosinus 
    		angle = acos(cosinus) * (180.0f / M_PI);
     
    		// calcul du signe en 2D, cf. seulement sur l'axe Z = utlisation des seules coordonnées X et Y
    		// signe = v1.x * v2.y - v1.y * v2.x; // partie Z du produit vectoriel entre V1 et V2
     
    		// calcul du signe en 3D selon l'axe de variation minimal à la place de l'axe XY
    		switch ( axe ) 
    		{
    			case 0 : signe = v1.y * v2.z - v1.z * v2.y; break; 
    			case 1 : signe = v1.z * v2.x - v1.x * v2.z; break;
    			case 2 : signe = v1.x * v2.y - v1.y * v2.x; break;
    		}
     
    		// "retournement" de l'angle si signe < 0, cf. gestion ordre CCW / CW
    		if ( signe < 0.0f )
    		{
    			angle += 180.0f;
    		}
     
     
    		Idx[i].v = i;
    		Idx[i].angle = angle;
     
    		// printf("Angle[%d] = %.0f \n", i, angle);
    	}  	
    }
     
    int Reindexation( const void *a, const void *b )
    {
    	indexed *pa, *pb;
     
    	pa = (indexed *) a;
    	pb = (indexed *) b;
     
    	return pa->angle - pb->angle;   
    }
     
     
    void PrintReindexed( v3f *v, int num, indexed *Idx, polygon *p )
    {
    	int i;
     
    	qsort( Idx, num, sizeof(indexed), Reindexation);
     
    	if ( p )  p->poly = num;
     
    	for ( i = 0 ; i < num ; i++ )
    	{
    		printf("v[%d -> %d] = { %.0f, %.0f, %.0f } [angle=%.0f] \n",
    			Idx[i].v, 
    			i,
    			v[ Idx[i].v ].x,
    			v[ Idx[i].v ].y,
    			v[ Idx[i].v ].z,
    			Idx[i].angle
    		);
     
    		if ( p ) p->gone[i] = Idx[i].v; 
    	}
    } 
     
    void PrintPolygon( polygon * p)
    {
    	int i;
     
    	printf("\nPolygon[%d] = [ ", p->poly);
     
    	for ( i = 0 ; i < p->poly ; i++ )
    	{
    		printf("%d ", p->gone[i] );
    	}
    	printf(" ] \n");
    }
     
     
     
     
     
    int main( int argc , char **argv )
    {
    	MakeQuadConnectivity();
     
    	printf("Avant reindexation \n");
    	PrintVertices(QuadVertices, 4);
     
    	printf("\nRéindexation ...\n\n");
    	ComputeAngles(QuadVertices, 4, Indexed);
     
    	PrintReindexed(QuadVertices, 4, Indexed, &Faces[0] );
     
    	PrintPolygon( &Faces[0] );
     
    	return 0;
    }
    Ce qui donne ça pour un calcul des angles à partir de l'axe X par exemple (because toutes les coordonnées x des sommets sont à 0)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    yannoo@cyclone ~/Dev/Facets $ make
    gcc facets.c -o facets -lm
    yannoo@cyclone ~/Dev/Facets $ ./facets
    Avant reindexation 
    v[0] = { 0 , 0 , 0 } 
    v[1] = { 0 , 1 , 1 } 
    v[2] = { 0 , 1 , 0 } 
    v[3] = { 0 , 0 , 1 } 
     
    Réindexation ...
     
    v[0 -> 0] = { 0, 0, 0 } [angle=0] 
    v[2 -> 1] = { 0, 1, 0 } [angle=90] 
    v[1 -> 2] = { 0, 1, 1 } [angle=180] 
    v[3 -> 3] = { 0, 0, 1 } [angle=270] 
     
    Polygon[4] = [ 0 2 1 3  ]
    => même pas du jeu : je n'ai même pas encore commencé à me friter avec les quaternions
    (je vais essayer d'optimiser/tester tout ça un peu plus avant de m'y frotter, histoire de voir si ça peut vraiment valoir le coup de prendre pas mal de temps en me fritant sur le sujet avec les quaternions, arbres BSP ou autres quadtrees/octrees ... )

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Graphe] Obtenir la meilleur combinaison d'arrete afin de passer par tous les sommets
    Par Djobird dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 15/04/2008, 22h56
  2. Réordonner les feuillets
    Par dessinateurttuyen dans le forum Visio
    Réponses: 0
    Dernier message: 04/02/2008, 11h06
  3. Réponses: 5
    Dernier message: 23/08/2007, 14h44
  4. [C#]Réordonner les élts d'un listView
    Par fafa139 dans le forum Windows Forms
    Réponses: 1
    Dernier message: 12/05/2006, 01h27
  5. [XSLT] Réordonner les éléments en sortie
    Par crossword dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 05/12/2005, 10h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo