1 /*
2 Copyright (C) 2003 Cedric Cellier, Dominique Lavault
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 */
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <assert.h>
21 #include <math.h>
22 #include <string.h>
23 #include "geom.h"
24 #include "csg.h"
25 #include "opengl.h"
26 #include "main.h"
27 #include "log.h"
28 #include "memspool.h"
29 #include "system.h"
30 
31 #ifndef M_PI
32 #define M_PI       3.14159265358979323846
33 #endif
34 
geom_b_box_union(b_box * dest_bb,b_box * bb1,b_box * bb2)35 void geom_b_box_union(b_box *dest_bb, b_box *bb1, b_box *bb2)
36 {
37 	int i;
38 	/* resulting b_box encloses both */
39 	if (bb1->vide) {
40 		if (bb2->vide) {
41 			dest_bb->vide=1;
42 			return;
43 		} else {
44 			memcpy(dest_bb, bb2, sizeof(*dest_bb));
45 			return;
46 		}
47 	}
48 	if (bb2->vide) {
49 		memcpy(dest_bb, bb1, sizeof(*dest_bb));
50 		return;
51 	}
52 	memcpy(dest_bb, bb1, sizeof(*dest_bb));
53 	for (i=0; i<3; i++) {
54 		if (dest_bb->p_min[i]>bb2->p_min[i]) dest_bb->p_min[i] = bb2->p_min[i];
55 		if (dest_bb->p_max[i]<bb2->p_max[i]) dest_bb->p_max[i] = bb2->p_max[i];
56 	}
57 }
58 
geom_b_box_intersection(b_box * dest_bb,b_box * bb1,b_box * bb2)59 void geom_b_box_intersection(b_box *dest_bb, b_box *bb1, b_box *bb2)
60 {
61 	int i;
62 	/* resulting b_box is the intersection of both */
63 	if (bb1->vide || bb2->vide) {
64 		dest_bb->vide = 1;
65 		return;
66 	}
67 	for (i=0; i<3; i++) {
68 		if (bb1->p_min[i]>bb2->p_min[i]) {
69 			dest_bb->p_min[i] = bb1->p_min[i];
70 		} else {
71 			dest_bb->p_min[i] = bb2->p_min[i];
72 		}
73 		if (bb1->p_max[i]<bb2->p_max[i]) {
74 			dest_bb->p_max[i] = bb1->p_max[i];
75 		} else {
76 			dest_bb->p_max[i] = bb2->p_max[i];
77 		}
78 		if (dest_bb->p_min[i]>dest_bb->p_max[i]) {
79 			dest_bb->vide = 1;
80 			return;
81 		}
82 	}
83 	dest_bb->vide = 0;
84 }
85 
geom_get_b_box(csg_node * node,b_box * dest_bb)86 void geom_get_b_box(csg_node *node, b_box *dest_bb)
87 {
88 	GLfloat pos[16];
89 	GLfloat size;
90 	GLfloat corner[7];
91 	unsigned i, j;
92 //	assert(node->type==CSG_PRIM);
93 	if (node->type!=CSG_PRIM) {
94 		csg_print_tree(node);
95 		gltv_log_fatal("Assertion node->type==CSG_PRIM failed. type=%d on :", node->type);
96 	}
97 	memcpy(pos, node->u.prim.m->pos->c, sizeof(pos));
98 	size = node->u.prim.m->prim->size_x;
99 	pos[0] *= size;
100 	pos[1] *= size;
101 	pos[2] *= size;
102 	size = node->u.prim.m->prim->size_y;
103 	pos[4] *= size;
104 	pos[5] *= size;
105 	pos[6] *= size;
106 	size = node->u.prim.m->prim->size_z;
107 	pos[8] *= size;
108 	pos[9] *= size;
109 	pos[10] *= size;
110 	for (i=0; i<3; i++) {
111 		dest_bb->p_min[i] = -pos[0+i] -pos[4+i] -pos[8+i] +pos[12+i];
112 		dest_bb->p_max[i] = dest_bb->p_min[i];
113 	}
114 	for (i=0; i<3; i++) {
115 		corner[0] = +pos[0+i] -pos[4+i] -pos[8+i] +pos[12+i];
116 		corner[1] = +pos[0+i] +pos[4+i] -pos[8+i] +pos[12+i];
117 		corner[2] = -pos[0+i] +pos[4+i] -pos[8+i] +pos[12+i];
118 		corner[3] = -pos[0+i] -pos[4+i] +pos[8+i] +pos[12+i];
119 		corner[4] = +pos[0+i] -pos[4+i] +pos[8+i] +pos[12+i];
120 		corner[5] = +pos[0+i] +pos[4+i] +pos[8+i] +pos[12+i];
121 		corner[6] = -pos[0+i] +pos[4+i] +pos[8+i] +pos[12+i];
122 		for (j=0; j<7; j++) {
123 			if (dest_bb->p_min[i]>corner[j]) dest_bb->p_min[i] = corner[j];
124 			if (dest_bb->p_max[i]<corner[j]) dest_bb->p_max[i] = corner[j];
125 		}
126 	}
127 	dest_bb->vide = 0;
128 }
129 
130 GLfloat *current_modelview=NULL, *current_projection=NULL;
131 
geom_set_current_modelview(GLfloat * pos)132 void geom_set_current_modelview(GLfloat *pos)
133 {
134 	current_modelview = pos;
135 }
geom_set_current_projection(GLfloat * proj)136 void geom_set_current_projection(GLfloat *proj)
137 {
138 	current_projection = proj;
139 }
140 
geom_matrix_mult(GLfloat * res,GLfloat * a,GLfloat * b)141 void geom_matrix_mult(GLfloat *res, GLfloat *a, GLfloat *b) {
142 	unsigned i,j,k;
143 	/* the hurry man strikes back */
144 	for (i=0; i<4; i++) {
145 		for (j=0; j<4; j++) {
146 			res[(j<<2)+i] = 0;
147 			for (k=0; k<4; k++) {
148 				res[(j<<2)+i] += a[i+(k<<2)]*b[(j<<2)+k];
149 			}
150 		}
151 	}
152 }
153 
geom_matrix_transp_ortho(GLfloat * res,GLfloat * m)154 void geom_matrix_transp_ortho(GLfloat *res, GLfloat *m)
155 {
156 	unsigned i,j;
157 	for (i=0; i<3; i++) {
158 		for (j=0; j<3; j++) {
159 			res[(i<<2)+j] = m[(j<<2)+i];
160 		}
161 		res[(i<<2)+3] = 0.;
162 	}
163 	for (i=0; i<3; i++) {
164 		res[12+i] = 0.;
165 		for (j=0; j<3; j++) {
166 			res[12+i] -= m[12+i]*res[(j<<2)+i];
167 		}
168 	}
169 	res[15] = 1;
170 }
171 
geom_set_identity(GLfloat * mat)172 void geom_set_identity(GLfloat *mat)
173 {
174 	unsigned i,j;
175 	for (i=0; i<4; i++) {
176 		for (j=0; j<4; j++) {
177 			mat[(i<<2)+j] = (i==j?1:0);
178 		}
179 	}
180 }
181 
geom_get_2d(GLfloat x,GLfloat y,GLfloat z,GLdouble * x2d,GLdouble * y2d,GLdouble * z2d)182 int geom_get_2d(GLfloat x, GLfloat y, GLfloat z, GLdouble *x2d, GLdouble *y2d, GLdouble *z2d)
183 {
184 	/* computes projection of a 3d point given current modelview and projection - returns 0 on error */
185 	/* the method of the hurry man : convert to double and use gluProject */
186 	GLint viewport[4] = { 0,0 };
187 	GLdouble modelview[16];
188 	GLdouble projection[16];
189 	unsigned i;
190 	assert(current_modelview!=NULL && current_projection!=NULL);
191 	viewport[2] = glut_fenLong;
192 	viewport[3] = glut_fenHaut;
193 	for (i=0; i<16; i++) {
194 		modelview[i] = current_modelview[i];
195 		projection[i] = current_projection[i];
196 	}
197 	return GL_TRUE == gluProject(x,y,z, modelview, projection, viewport, x2d,y2d,z2d);
198 }
199 
geom_get_b_box_2d(b_box * box3d,b_box_2d * box2d)200 void geom_get_b_box_2d(b_box *box3d, b_box_2d *box2d)
201 {
202 	/* computes the 2d bounding box from a 3d bounding box, the current camera and current projection */
203 	GLdouble x[8], y[8], z;
204 	unsigned i;
205 	if (box3d->vide) {
206 		box2d->vide=1;
207 		return;
208 	}
209 	i = geom_get_2d(box3d->p_min[0], box3d->p_min[1], box3d->p_min[2], &x[0], &y[0], &z);
210 	i += geom_get_2d(box3d->p_min[0], box3d->p_min[1], box3d->p_max[2], &x[1], &y[1], &z);
211 	i += geom_get_2d(box3d->p_min[0], box3d->p_max[1], box3d->p_min[2], &x[2], &y[2], &z);
212 	i += geom_get_2d(box3d->p_min[0], box3d->p_max[1], box3d->p_max[2], &x[3], &y[3], &z);
213 	i += geom_get_2d(box3d->p_max[0], box3d->p_min[1], box3d->p_min[2], &x[4], &y[4], &z);
214 	i += geom_get_2d(box3d->p_max[0], box3d->p_min[1], box3d->p_max[2], &x[5], &y[5], &z);
215 	i += geom_get_2d(box3d->p_max[0], box3d->p_max[1], box3d->p_min[2], &x[6], &y[6], &z);
216 	i += geom_get_2d(box3d->p_max[0], box3d->p_max[1], box3d->p_max[2], &x[7], &y[7], &z);
217 	if (8!=i) gltv_log_fatal("geom_get_b_box_2_d: invalid coordinates");
218 	box2d->xmin = box2d->xmax = x[0];
219 	box2d->ymin = box2d->ymax = y[0];
220 	for (i=1; i<8; i++) {
221 		if (x[i]<box2d->xmin) box2d->xmin=x[i];
222 		if (y[i]<box2d->ymin) box2d->ymin=y[i];
223 		if (x[i]>box2d->xmax) box2d->xmax=x[i];
224 		if (y[i]>box2d->ymax) box2d->ymax=y[i];
225 	}
226 	if (box2d->xmax>=glut_fenLong) box2d->xmax = glut_fenLong;
227 	if (box2d->ymax>=glut_fenHaut) box2d->ymax = glut_fenHaut;
228 	if (box2d->xmin<=0) box2d->xmin=0;
229 	if (box2d->ymin<=0) box2d->ymin=0;
230 	if (box2d->xmin>=box2d->xmax || box2d->ymin>=box2d->ymax) {
231 		box2d->vide=1;
232 	} else {
233 		box2d->vide = 0;
234 	}
235 //	gltv_log_warning(GLTV_LOG_MUSTSEE, "box2d : %d %d - %d %d - %d\n", box2d->xmin, box2d->ymin, box2d->xmax, box2d->ymax, (int)box2d->vide);
236 }
237 
geom_b_box_intersects(b_box * bb1,b_box * bb2)238 int geom_b_box_intersects(b_box *bb1, b_box *bb2)
239 {
240 	/* tels wether 2 b_box have an intersection */
241 	b_box inter;
242 	geom_b_box_intersection(&inter, bb1, bb2);
243 	return !inter.vide;
244 }
245 
geom_rapproche(GLfloat * a,GLfloat * b,float ratio)246 void geom_rapproche(GLfloat *a, GLfloat *b, float ratio) {
247 	float d;
248 	unsigned i;
249 	for (i=0; i<3; i++) {
250 		d = (b[i] - a[i])*ratio;
251 		a[i] += d;
252 	}
253 }
254 
geom_scalaire(GLfloat * a,GLfloat * b)255 float geom_scalaire(GLfloat *a, GLfloat *b)
256 {
257 	return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];
258 }
259 
geom_norme(GLfloat * a)260 float geom_norme(GLfloat *a)
261 {
262 	return sqrt(geom_scalaire(a,a));
263 }
264 
geom_normalise(GLfloat * a)265 void geom_normalise(GLfloat *a)
266 {
267 	double n = geom_norme(a);
268 	if (0!=n) {
269 		a[0] /= n;
270 		a[1] /= n;
271 		a[2] /= n;
272 	}
273 }
274 
geom_orthogonalise(GLfloat * a,GLfloat * b)275 void geom_orthogonalise(GLfloat *a, GLfloat *b)
276 {
277 	double d = geom_scalaire(a,b);
278 	if (0!=d) {
279 		d /= geom_scalaire(b,b);
280 		a[0] -= d*b[0];
281 		a[1] -= d*b[1];
282 		a[2] -= d*b[2];
283 	}
284 }
285 
geom_vectoriel(GLfloat * a,GLfloat * b,GLfloat * c)286 void geom_vectoriel(GLfloat *a, GLfloat *b, GLfloat *c)
287 {
288 	c[0] = a[1]*b[2]-a[2]*b[1];
289 	c[1] = a[2]*b[0]-a[0]*b[2];
290 	c[2] = a[0]*b[1]-a[1]*b[0];
291 }
292 
geom_position_approche(GLfloat * now,GLfloat * target,float ratio)293 void geom_position_approche(GLfloat *now, GLfloat *target, float ratio)
294 {
295 	/* translation */
296 	geom_rapproche(now+12, target+12, ratio);
297 	/* axis */
298 	/* begin with z */
299 	geom_rapproche(now+8, target+8, ratio);
300 	geom_rapproche(now+4, target+4, ratio);
301 	geom_normalise(now+4);
302 	geom_orthogonalise(now+8, now+4);
303 	geom_normalise(now+8);
304 	geom_vectoriel(now+4, now+8, now+0);
305 }
306 
geom_is_Pt_in_2DTriangle(struct Point2D * P,struct Point2D * p0,struct Point2D * p1,struct Point2D * p2)307 int  geom_is_Pt_in_2DTriangle(struct Point2D * P, struct Point2D * p0, struct Point2D * p1, struct Point2D * p2)
308 {
309 	struct Point2D V[4];
310 	int i=0,  cn = 0;	// the crossing number counter
311 
312 	V[i++] =* p0;
313 	V[i++] =* p1;
314 	V[i++] =* p2;
315 	V[i++] =* p0;
316 	// loop through all edges of the polygon
317 	for (i=0; i<3; i++) {	// edge from V[i] to V[i+1]
318 	   if (((V[i].y <= P->y) && (V[i+1].y > P->y))	// an upward crossing
319 		|| ((V[i].y > P->y) && (V[i+1].y <= P->y))) { // a downward crossing
320 			// compute the actual edge-ray intersect x-coordinate
321 			float vt = (float)(P->y - V[i].y) / (V[i+1].y - V[i].y);
322 			if (P->x < V[i].x + vt * (V[i+1].x - V[i].x)) // P->x < intersect
323 				++cn;   // a valid crossing of y=P->y right of P->x
324 		}
325 	}
326 	return (cn&1);	// 0 if even (out), and 1 if odd (in)
327 }
328 
geom_get_3d(GLdouble x,GLdouble y,GLdouble z,GLdouble * x3d,GLdouble * y3d,GLdouble * z3d)329 int geom_get_3d(GLdouble x, GLdouble y, GLdouble z, GLdouble *x3d, GLdouble *y3d, GLdouble *z3d)
330 {
331 	GLint viewport[4] = { 0,0 };
332 	GLdouble modelview[16];
333 	GLdouble projection[16];
334 	unsigned i;
335 	assert(current_modelview!=NULL && current_projection!=NULL);
336 	viewport[2] = glut_fenLong;
337 	viewport[3] = glut_fenHaut;
338 	for (i=0; i<16; i++) {
339 		modelview[i] = current_modelview[i];
340 		projection[i] = current_projection[i];
341 	}
342 	return GL_TRUE == gluUnProject(x,y,z, modelview, projection, viewport, x3d,y3d,z3d);
343 }
344 
geom_prim_clicked(primitive * prim)345 int geom_prim_clicked(primitive *prim)
346 {
347 	unsigned cptPts, cptPoly, nbPts, nbFaces;
348 	GLfloat* points;
349 	GLuint* faces;
350 	GLdouble dummy;
351 	int o, ret=0;
352 	struct Point2D *pts2D, p_mouseClickCoordinates;
353 	p_mouseClickCoordinates.x = (glut_mouse_x+1)*.5*glut_fenLong;
354 	p_mouseClickCoordinates.y = (1-glut_mouse_y)*.5*glut_fenHaut;
355 	if (prim->nb_points_light) {
356 		nbPts = prim->nb_points_light;
357 		nbFaces = prim->nb_faces_light;
358 		points = prim->points_light;
359 		faces = prim->faces_light;
360 	} else {
361 		nbPts = prim->nb_points;
362 		nbFaces = prim->nb_faces;
363 		points = prim->points;
364 		faces = prim->faces;
365 	}
366 	pts2D = gltv_memspool_alloc(sizeof(*pts2D)*nbPts);
367 	for (o=0, cptPts=0; cptPts<nbPts; cptPts++, o+=3) {
368 		geom_get_2d(points[o],points[o+1],points[o+2], &pts2D[cptPts].x,&pts2D[cptPts].y,&dummy);
369 	}
370 /*	glBegin(GL_LINES);
371 	glColor3f(1,1,0);
372 	glVertex3f(0, 0, -1.0001);
373 	glVertex3f(p_mouseClickCoordinates.x, p_mouseClickCoordinates.y, -1.0001);
374 	glEnd();*/
375 	for (cptPoly=0; cptPoly<nbFaces; cptPoly++) {
376 /*		glBegin(GL_LINES);
377 		glColor3f(1,0,1);
378 		glVertex3f(pts2D[faces[cptPoly*3+0]].x, pts2D[faces[cptPoly*3+0]].y, -1.0001);
379 		glVertex3f(pts2D[faces[cptPoly*3+1]].x, pts2D[faces[cptPoly*3+1]].y, -1.0001);
380 		glVertex3f(pts2D[faces[cptPoly*3+0]].x, pts2D[faces[cptPoly*3+0]].y, -1.0001);
381 		glVertex3f(pts2D[faces[cptPoly*3+2]].x, pts2D[faces[cptPoly*3+2]].y, -1.0001);
382 		glEnd();*/
383 		if (geom_is_Pt_in_2DTriangle(&p_mouseClickCoordinates, &pts2D[faces[cptPoly*3+0]],&pts2D[faces[cptPoly*3+1]],&pts2D[faces[cptPoly*3+2]])) {
384 			ret = 1;
385 			break;
386 		}
387 	}
388 	gltv_memspool_unregister(pts2D);
389 	return ret;
390 }
391 
geom_prim_depth(primitive * prim)392 GLfloat geom_prim_depth(primitive *prim)
393 {
394 	/* as center is at (0,0,0), easy calculus (check that prims are still centered) */
395 	return current_modelview[14]; /* :-p */
396 }
397 
geom_clic_position(position * pos,GLfloat * z)398 mesh *geom_clic_position(position *pos, GLfloat *z)
399 {
400 	/* go throught all meshes of this position, computing
401 	 * the position of every meshes, and look for a clicked mesh.
402 	 * Return NULL if none found, or mesh
403 	 */
404 	GLfloat m[16], zz, *old_current;
405 	unsigned s;
406 	mesh *clicked = NULL, *oo;
407 	geom_matrix_mult(m, current_modelview, pos->c);
408 	old_current = current_modelview;
409 	geom_set_current_modelview(m);
410 /*	glPushMatrix();
411 	glLoadIdentity();*/
412 	for (s=0; s<pos->nb_sons; s++) {
413 		oo = geom_clic_position(pos->sons[s], &zz);
414 		if (oo!=NULL && (clicked==NULL || zz>*z)) {
415 			clicked = oo;
416 			*z = zz;
417 		}
418 	}
419 	for (s=0; s<pos->nb_meshes; s++) {
420 		if (geom_prim_clicked(pos->meshes[s]->prim)) {
421 			zz = geom_prim_depth(pos->meshes[s]->prim);
422 			if (clicked==NULL || zz>*z) {
423 				clicked = pos->meshes[s];
424 				*z = zz;
425 			}
426 		}
427 	}
428 
429 	geom_set_current_modelview(old_current);
430 //	glPopMatrix();
431 	return clicked;
432 }
433 
geom_get_pos_diff(GLfloat * dest,GLfloat * m1,GLfloat * m2)434 static void geom_get_pos_diff(GLfloat *dest, GLfloat *m1, GLfloat *m2)
435 {
436 	static GLfloat m1T[16];
437 	geom_matrix_transp_ortho(m1T, m1);
438 	geom_matrix_mult(dest, m1T, m2);
439 }
440 
geom_axes_match(GLfloat * v1,GLfloat * v2)441 static int geom_axes_match(GLfloat *v1, GLfloat *v2)
442 {
443 	unsigned i;
444 	gltv_log_warning(GLTV_LOG_DEBUG, "\t\t\tdo (%f,%f,%f) matches (%f,%f,%f)?", v1[0],v1[1],v1[2],v2[0],v2[1],v2[2]);
445 	for (i=0; i<3; i++) {
446 		if (fabs(v1[i]-v2[i])>.1) return 0;
447 	}
448 	return 1;
449 }
450 
geom_axes_unsigmatch(GLfloat * v1,GLfloat * v2)451 static int geom_axes_unsigmatch(GLfloat *v1, GLfloat *v2)
452 {
453 	unsigned i;
454 	gltv_log_warning(GLTV_LOG_DEBUG, "\t\t\tdo (%f,%f,%f) matches +/-(%f,%f,%f)?", v1[0],v1[1],v1[2],v2[0],v2[1],v2[2]);
455 	for (i=0; i<3; i++) {
456 		if (fabs(fabs(v1[i])-fabs(v2[i]))>.1) return 0;
457 	}
458 	for (i=0; i<3; i++) {
459 		if (fabs(v1[i]+v2[i])>.1) return 1;
460 	}
461 	return -1;
462 }
463 
geom_pos_are_equivalent(GLfloat * m1,GLfloat * m2,unsigned sym2)464 static int geom_pos_are_equivalent(GLfloat *m1, GLfloat *m2, unsigned sym2)
465 {
466 	/* Ts should be equals */
467 	gltv_log_warning(GLTV_LOG_DEBUG, "\t\tT match ?");
468 	if (!geom_axes_match(m1+12,m2+12)) {
469 		gltv_log_warning(GLTV_LOG_DEBUG, "\t\tno");
470 		return 0;
471 	}
472 	gltv_log_warning(GLTV_LOG_DEBUG, "\t\tyes\n\t\tsym = %u", sym2);
473 	/* We dont handle every possible symmetry because we lack the time */
474 	if (0==sym2) {
475 		return geom_axes_match(m1, m2) && geom_axes_match(m1+4, m2+4) && geom_axes_match(m1+8, m2+8);
476 	} else if (ROT_X_45+ROT_Y_45+ROT_Z_45==sym2) {
477 		return 1;
478 	} else if (ROT_X_45==sym2) {
479 		return geom_axes_match(m1, m2);
480 	} else if (ROT_Y_45==sym2) {
481 		return geom_axes_match(m1+4, m2+4);
482 	} else if (ROT_Z_45==sym2) {
483 		return geom_axes_match(m1+8, m2+8);
484 	} else if (ROT_X_45+ROT_Y_90+ROT_Z_90==sym2) {
485 		return geom_axes_unsigmatch(m1, m2);
486 	} else if (ROT_X_90+ROT_Y_45+ROT_Z_90==sym2) {
487 		return geom_axes_unsigmatch(m1+4, m2+4);
488 	} else if (ROT_X_90+ROT_Y_90+ROT_Z_45==sym2) {
489 		return geom_axes_unsigmatch(m1+8, m2+8);
490 	} else if (ROT_X_90==sym2) {
491 		return geom_axes_match(m1, m2) && (geom_axes_unsigmatch(m1+4,m2+4)*geom_axes_unsigmatch(m1+8,m2+8))==1;
492 	} else if (ROT_Y_90==sym2) {
493 		return geom_axes_match(m1+4, m2+4) && (geom_axes_unsigmatch(m1,m2)*geom_axes_unsigmatch(m1+8,m2+8))==1;
494 	} else if (ROT_Z_90==sym2) {
495 		return geom_axes_match(m1+8, m2+8) && (geom_axes_unsigmatch(m1+4,m2+4)*geom_axes_unsigmatch(m1,m2))==1;
496 	} else {
497 		gltv_log_fatal("symmetry not handled for now : %u", sym2);
498 	}
499 }
500 
geom_pos_is_equivalent(mesh ** m,GLfloat (* pos)[16],unsigned nb_pos)501 int geom_pos_is_equivalent(mesh **m, GLfloat (*pos)[16], unsigned nb_pos)
502 {
503 	static GLfloat diff[2][16];
504 	unsigned p;
505 	GLfloat s[2];
506 	char k[2];
507 	static GLfloat posInit[16];
508 	if (nb_pos<2) return 1;
509 	posInit[12] = m[0]->pos->c[12];
510 	posInit[13] = m[0]->pos->c[13];
511 	posInit[14] = m[0]->pos->c[14];
512 	posInit[15] = 1.;
513 	gltv_log_warning(GLTV_LOG_DEBUG, "Are positions equivalents ?");
514 	/* TODO : au lieu de prendre le premier mesh comme r�f�rence, prendre celui qui � le moins de symetrie ... imagine que ce soit une sphere le premier mesh ! */
515 	for (s[0]=-1; s[0]<=1; s[0]+=2) {
516 		for (s[1]=-1; s[1]<=1; s[1]+=2) {
517 			for (k[0]=0; k[0]<3; k[0]++) {
518 				for (k[1]=0; k[1]<3; k[1]++) {
519 					unsigned i,j;
520 					if (k[0]==k[1]) continue;
521 					for (i=0; i<2; i++) {
522 						for (j=0; j<3; j++) {
523 							if (k[i]==j) posInit[(i<<2)+j] = s[i];
524 							else posInit[(i<<2)+j] = 0;
525 						}
526 						geom_vectoriel(posInit, posInit+4, posInit+8);
527 						if (geom_pos_are_equivalent(m[0]->pos->c, posInit, m[0]->prim->symmetry)) {
528 							for (p=0; p<nb_pos; p++) {
529 								geom_get_pos_diff(diff[0], posInit, m[p]->pos->c);
530 								geom_get_pos_diff(diff[1], &pos[0][0], &pos[p][0]);
531 								gltv_log_warning(GLTV_LOG_DEBUG, "\tpositions of prim %u for prim 0 equivalents ?", p);
532 								if (!geom_pos_are_equivalent(diff[0], diff[1], m[p]->prim->symmetry)) {
533 									gltv_log_warning(GLTV_LOG_DEBUG, "\tno");
534 									break;
535 								}
536 								gltv_log_warning(GLTV_LOG_DEBUG, "\tyes");
537 							}
538 							if (p==nb_pos) return 1;
539 						}
540 					}
541 				}
542 			}
543 		}
544 	}
545 	return 0;
546 }
547