FreeWRL / FreeX3D 4.3.0
Polyrep.c
1/*
2
3
4???
5
6*/
7
8/****************************************************************************
9 This file is part of the FreeWRL/FreeX3D Distribution.
10
11 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
12
13 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
14 it under the terms of the GNU Lesser Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
25****************************************************************************/
26
27
28
29#include <config.h>
30#include <system.h>
31#include <display.h>
32#include <internal.h>
33
34#include <libFreeWRL.h>
35
36#include "../vrml_parser/Structs.h"
37#include "../main/headers.h"
38#include "../opengl/Frustum.h"
39#include "../opengl/Material.h"
40#include "../opengl/OpenGL_Utils.h"
41#include "../opengl/Textures.h"
42#include "../scenegraph/Component_Shape.h"
43#include "../scenegraph/RenderFuncs.h"
44
45#include "Polyrep.h"
46#include "LinearAlgebra.h"
47#include "Tess.h"
48
49void * compile_poly_if_required(void* node, void* coord, void* fogCoord, void* color, void* normal, void* texCoord) {
50//#define COMPILE_POLY_IF_REQUIRED(a,b,c,d,e)
51//if(!compile_poly_if_required(node,a,b,c,d,e))return;
52 struct X3D_Node* nd = X3D_NODE(node);
53 if(!nd->_intern || nd->_change != ((struct X3D_PolyRep *)(nd->_intern))->irep_change) { \
54 compileNode ((void *)compile_polyrep,node,coord,fogCoord,color,normal,texCoord);
55 }
56 return nd->_intern;
57}
58
59/* How many faces are in this IndexedFaceSet? */
60
61int count_IFS_faces(int cin, struct Multi_Int32 *coordIndex, struct facepar *faceok) {
62 /* lets see how many faces we have */
63 int pointctr=0;
64 int max_points_per_face = 0;
65 int min_points_per_face = 99999;
66 int i;
67 int faces = 0;
68
69 if (coordIndex == NULL) return 0;
70 if (coordIndex->n == 0) return 0;
71 faceok[faces].start = 0;
72 for(i=0; i<cin; i++) {
73
74 if((coordIndex->p[i] == -1) || (i==cin-1)) {
75 faceok[faces].end = i-1;
76
77 if(coordIndex->p[i] != -1) {
78 faceok[faces].end = i;
79 pointctr++;
80 }
81
82 faces++;
83 faceok[faces].start = i+1;
84 if (pointctr > max_points_per_face)
85 max_points_per_face = pointctr;
86 if (pointctr < min_points_per_face)
87 min_points_per_face = pointctr;
88 pointctr = 0;
89 } else pointctr++;
90 }
91
92
93 /*
94 printf ("this structure has %d faces\n",faces);
95 printf (" max points per face %d\n",max_points_per_face);
96 printf (" min points per face %d\n\n",min_points_per_face);
97 */
98
99 if (faces < 1) {
100 /* printf("an IndexedFaceSet with no faces found\n"); */
101 return (0);
102 }
103 return faces;
104}
105
106
107/* Generate the normals for each face of an IndexedFaceSet */
108/* create two datastructures: */
109/* - face normals; given a face, tell me the normal */
110/* - point-face; for each point, tell me the face(s) */
111
112int IFS_face_normals (
113 struct SFVec3f *facenormals, //struct point_XYZ *facenormals,
114 struct facepar *faceok,
115 int *pointfaces,
116 int faces,
117 int npoints,
118 int cin,
119 struct SFVec3f *points,
120 struct Multi_Int32 *coordIndex,
121 int ccw) {
122
123 int tmp_a = 0, this_face_finished;
124 int i,checkpoint;
125 int facectr;
126 int pt_1, pt_2, pt_3;
127 float AC, BC;
128 struct SFVec3f *c1,*c2,*c3;
129 float a[3]; float b[3];
130
131 int retval = FALSE;
132 int new_way = TRUE;
133
134 float this_vl;
135 //struct point_XYZ thisfaceNorms;
136
137 /* printf ("IFS_face_normals, faces %d\n",faces); */
138
139 /* Assume each face is ok for now*/
140 for(i=0; i<faces; i++) {
141 faceok[i].OK = TRUE;
142 //printf("face %d start %d end %d\n",i,faceok[i].start,faceok[i].end);
143 }
144
145 /* calculate normals for each face*/
146 for(i=0; i<faces; i++) {
147 /* lets decide which normal to choose here, in case of more than 1 triangle.
148 we choose the triangle with the greatest vector length hoping that it is
149 the least "degenerate" of them all */
150 this_vl = 0.0f;
151 //facenormals[i].x = 0.0;
152 //facenormals[i].y = 0.0;
153 //facenormals[i].z = 1.0;
154 vecset3f(facenormals[i].c,0.0f, 0.0f, 1.0f);
155
156 if((faceok[i].end - faceok[i].start + 1) < 3) {
157 printf ("IndexedFaceNormals: have a face with two or less vertexes\n");
158 faceok[i].OK = FALSE;
159 }
160 if(faceok[i].OK){
161 /* check to see that the coordIndex does not point to a
162 point that is outside the range of our point array */
163 for(int k=faceok[i].start;k<=faceok[i].end;k++){
164 checkpoint = coordIndex->p[k];
165 if (checkpoint < 0 || checkpoint >= npoints) {
166 printf ("Indexed Geometry face %d has a point out of range,",i);
167 printf (" point is %d, should be between 0 and %d\n", checkpoint,npoints-1);
168 faceok[i].OK = FALSE;
169 }
170 }
171 }
172 /* face has passed checks so far... */
173 if (faceok[i].OK) {
174 /* printf ("face %d ok\n",i); */
175 /* check for degenerate triangles -- we go through all triangles in a face to see which
176 triangle has the largest vector length */
177 this_face_finished = FALSE;
178 tmp_a = faceok[i].start;
179 pt_1 = tmp_a;
180 //printf("face %d first index pt_1 %d\n",i,pt_1);
181 if (ccw) {
182 /* printf ("IFS face normals CCW\n"); */
183 pt_2 = tmp_a+1; pt_3 = tmp_a+2;
184 } else {
185 /* printf ("IFS face normals *NOT* CCW\n"); */
186 pt_3 = tmp_a+1; pt_2 = tmp_a+2;
187 }
188
189 do {
190 float fnorm[3], fnormlen, delta[3];
191 //printf("do pt1 %d pt2 %d pt3 %d\n",pt_1,pt_2,pt_3);
192
193 /* first three coords give us the normal */
194 c1 = &(points[coordIndex->p[pt_1]]);
195 c2 = &(points[coordIndex->p[pt_2]]);
196 c3 = &(points[coordIndex->p[pt_3]]);
197
198 //a[0] = c2->c[0] - c1->c[0];
199 //a[1] = c2->c[1] - c1->c[1];
200 //a[2] = c2->c[2] - c1->c[2];
201 //b[0] = c3->c[0] - c1->c[0];
202 //b[1] = c3->c[1] - c1->c[1];
203 //b[2] = c3->c[2] - c1->c[2];
204 vecdif3f(a,c2->c,c1->c);
205 vecdif3f(b,c3->c,c1->c);
206
207 //printf ("a0 %f a1 %f a2 %f b0 %f b1 %f b2 %f\n", a[0],a[1],a[2],b[0],b[1],b[2]);
208
209 //thisfaceNorms.x = a[1]*b[2] - b[1]*a[2];
210 //thisfaceNorms.y = -(a[0]*b[2] - b[0]*a[2]);
211 //thisfaceNorms.z = a[0]*b[1] - b[0]*a[1];
212 veccross3f(fnorm,a,b);
213 /* printf ("vector length is %f\n",calc_vector_length (thisfaceNorms)); */
214 //printf("axb=%f %f %f\n",fnorm[0],fnorm[1],fnorm[2]);
215 /* is this vector length greater than a previous one? */
216 //if (calc_vector_length(thisfaceNorms) > this_vl) {
217 fnormlen= veclength3f(fnorm);
218 if(fnormlen > this_vl) {
219 /* printf ("for face, using points %d %d %d\n",pt_1, pt_2, pt_3); */
220 this_vl = fnormlen; //calc_vector_length(thisfaceNorms);
221 veccopy3f(facenormals[i].c,fnorm);
222 //facenormals[i].x = thisfaceNorms.x;
223 //facenormals[i].y = thisfaceNorms.y;
224 //facenormals[i].z = thisfaceNorms.z;
225 }
226
227 /* lets skip along to next triangle in this face */
228
229 //AC=(c1->c[0]-c3->c[0])*(c1->c[1]-c3->c[1])*(c1->c[2]-c3->c[2]);
230 //BC=(c2->c[0]-c3->c[0])*(c2->c[1]-c3->c[1])*(c2->c[2]-c3->c[2]);
231 AC = veclength3f(vecdif3f(delta,c1->c,c2->c));
232 BC = veclength3f(vecdif3f(delta,c2->c,c3->c));
233 /* printf ("AC %f ",AC); printf ("BC %f \n",BC); */
234
235 /* we have 3 points, a, b, c */
236 /* we also have 3 vectors, AB, AC, BC */
237 /* find out which one looks the closest one to skip out */
238 /* either we move both 2nd and 3rd points, or just the 3rd */
239
240 if (ccw) {
241 /* printf ("moving along IFS face normals CCW\n"); */
242 //if (fabs(AC) < fabs(BC)) { pt_2++; }
243 if (AC < BC) { pt_2++; }
244 pt_3++;
245 } else {
246 /* printf ("moving along IFS face normals *NOT* CCW\n"); */
247 /* if (fabs(AC) < fabs(BC)) { pt_3++; } */
248 pt_2++;
249 }
250
251 /* skip forward to the next couple of points - if possible */
252 /* printf ("looking at %d, cin is %d\n",tmp_a, cin); */
253 tmp_a ++;
254 this_face_finished = tmp_a + 2 > faceok[i].end;
255 } while (!this_face_finished);
256
257 if (APPROX(this_vl,0.0)) {
258 /* printf ("face %d is degenerate\n",i); */
259 faceok[i].OK = FALSE;
260 } else {
261 /* printf ("face %d is ok\n",i); */
262 //normalize_vector(&facenormals[i]);
263 vecnormalize3f(facenormals[i].c,facenormals[i].c);
264
265 /*
266 printf ("vertices \t%f %f %f\n\t\t%f %f %f\n\t\t%f %f %f\n",
267 c1->c[0],c1->c[1],c1->c[2],
268 c2->c[0],c2->c[1],c2->c[2],
269 c3->c[0],c3->c[1],c3->c[2]);
270 */
271 //printf ("face %3d normal %5.2f %5.2f %5.2f\n",i,facenormals[i].c[0],facenormals[i].c[1],facenormals[i].c[2]);
272
273 }
274
275
276 }
277
278 // printf ("for face %d, vec len is %f\n",i,this_vl);
279 }
280
281
282 /* do we have any valid faces??? */
283 for(i=0; i<faces; i++) {
284 if (faceok[i].OK == TRUE) {
285 retval = TRUE;
286 }
287 }
288 if (!retval)
289 return retval; /* nope, lets just drop out of here */
290
291
292 /* now, go through each face, and make a point-face list
293 so that I can give it a point later, and I will know which face(s)
294 it belong to that point */
295 /* printf ("\nnow generating point-face list\n"); */
296 for (i=0; i<npoints; i++) { pointfaces[i*POINT_FACES]=0; }
297 if(new_way){
298 for(i=0;i<faces;i++){
299 if(faceok[i].OK)
300 for(int j=faceok[i].start;j<=faceok[i].end;j++){
301 tmp_a = coordIndex->p[j];
302 //printf ("pointfaces, coord %d coordIndex %d face %d\n",j,tmp_a,i);
303 tmp_a *= POINT_FACES;
304 add_to_face (tmp_a,i,pointfaces);
305 }
306 }
307 }else{ //new way
308 facectr=0;
309 for(i=0; i<cin; i++) {
310 tmp_a=coordIndex->p[i];
311 if (tmp_a == -1) {
312 facectr++;
313 } else {
314 if (faceok[facectr].OK) {
315 //printf ("pointfaces, coord %d coordIndex %d face %d\n",i,tmp_a,facectr);
316 tmp_a*=POINT_FACES;
317 add_to_face (tmp_a,facectr,pointfaces);
318 } else {
319 // printf ("skipping add_to_face for invalid face %d\n",facectr);
320 }
321 }
322 }
323 } //new way
324
325 /*
326 printf ("\ncheck \n");
327 for (i=0; i<npoints; i++) {
328 int tmp_b;
329
330 tmp_a = i*POINT_FACES;
331 printf ("point %d is in %d faces, these are:\n ", i, pointfaces[tmp_a]);
332 for (tmp_b=0; tmp_b<pointfaces[tmp_a]; tmp_b++) {
333 printf ("%d ",pointfaces[tmp_a+tmp_b+1]);
334 }
335 printf ("\n");
336 }
337 */
338
339 return retval;
340}
341
342
343
344/* Tesselated faces MAY have the wrong normal calculated. re-calculate after tesselation */
345
346void Extru_check_normal (
347 struct SFVec3f *facenormals, //struct point_XYZ *facenormals,
348 int this_face,
349 int direction,
350 struct X3D_PolyRep *rep_,
351 int ccw) {
352
353 /* only use this after tesselator as we get coord indexes from global var */
354 struct SFVec3f *c1,*c2,*c3;
355 float a[3], b[3], fnorm[3], fnormlen;
356 int zz1, zz2;
357 ttglobal tg = gglobal();
358
359 if (ccw) {
360 zz1 = 1;
361 zz2 = 2;
362 } else {
363 zz1 = 2;
364 zz2 = 1;
365 }
366
367 /* first three coords give us the normal */
368 c1 = (struct SFVec3f *) &rep_->actualCoord[3*tg->Tess.global_IFS_Coords[0]];
369 c2 = (struct SFVec3f *) &rep_->actualCoord[3*tg->Tess.global_IFS_Coords[zz1]];
370 c3 = (struct SFVec3f *) &rep_->actualCoord[3*tg->Tess.global_IFS_Coords[zz2]];
371
372 /*printf ("Extru_check_normal, coords %d %d %d\n",global_IFS_Coords[0],
373 global_IFS_Coords[1],global_IFS_Coords[2]);
374 printf ("Extru_check_normal vertices \t%f %f %f\n\t\t%f %f %f\n\t\t%f %f %f\n",
375 c1->c[0],c1->c[1],c1->c[2],
376 c2->c[0],c2->c[1],c2->c[2],
377 c3->c[0],c3->c[1],c3->c[2]);
378 */
379
380 a[0] = c2->c[0] - c1->c[0];
381 a[1] = c2->c[1] - c1->c[1];
382 a[2] = c2->c[2] - c1->c[2];
383 b[0] = c3->c[0] - c1->c[0];
384 b[1] = c3->c[1] - c1->c[1];
385 b[2] = c3->c[2] - c1->c[2];
386 vecdif3f(a,c2->c,c1->c);
387 vecdif3f(b,c3->c,c1->c);
388 veccross3f(fnorm,a,b);
389
390 //facenormals[this_face].x = a[1]*b[2] - b[1]*a[2] * direction;
391 //facenormals[this_face].y = -(a[0]*b[2] - b[0]*a[2]) * direction;
392 //facenormals[this_face].z = a[0]*b[1] - b[0]*a[1] * direction;
393 fnormlen = veclength3f(fnorm);
394 //if (APPROX(calc_vector_length (facenormals[this_face]),0.0)) {
395 if (APPROX(fnormlen,0.0f)) {
396 ConsoleMessage ("WARNING: FreeWRL got degenerate triangle; OpenGL tesselator should not give degenerate triangles back %f\n",
397 fnormlen); //fabs(calc_vector_length (facenormals[this_face])));
398 }
399 vecnormalize3f(facenormals[this_face].c,fnorm);
400
401 //normalize_vector(&facenormals[this_face]);
402 /* printf ("facenormal for %d is %f %f %f\n",this_face, facenormals[this_face].x,
403 facenormals[this_face].y, facenormals[this_face].z); */
404}
405
406/* Tesselated faces MAY have the wrong normal calculated. re-calculate after tesselation */
407
408
409void IFS_check_normal (
410 struct SFVec3f *facenormals, //struct point_XYZ *facenormals,
411 int this_face,
412 struct SFVec3f *points, int base,
413 struct Multi_Int32 *coordIndex, int ccw) {
414
415 struct SFVec3f *c1,*c2,*c3;
416 float a[3], b[3], fnorm[3], fnormlen;
417 ttglobal tg = gglobal();
418
419 /* printf ("IFS_check_normal, base %d points %d %d %d\n",base,*/
420 /* global_IFS_Coords[0],global_IFS_Coords[1],global_IFS_Coords[2]);*/
421 /* printf ("normal was %f %f %f\n\n",facenormals[this_face].x,*/
422 /* facenormals[this_face].y,facenormals[this_face].z);*/
423
424 //PROBLEM IF THE FIRST TRIANGLE OF A FACE IS DEGENERATE, THEN
425 // WE GET A DEGENERATE NORMAL / NO NORMAL
426 /* first three coords give us the normal */
427 c1 = &(points[coordIndex->p[base+tg->Tess.global_IFS_Coords[0]]]);
428 if (ccw) {
429 c2 = &(points[coordIndex->p[base+tg->Tess.global_IFS_Coords[1]]]);
430 c3 = &(points[coordIndex->p[base+tg->Tess.global_IFS_Coords[2]]]);
431 } else {
432 c3 = &(points[coordIndex->p[base+tg->Tess.global_IFS_Coords[1]]]);
433 c2 = &(points[coordIndex->p[base+tg->Tess.global_IFS_Coords[2]]]);
434 }
435
436 a[0] = c2->c[0] - c1->c[0];
437 a[1] = c2->c[1] - c1->c[1];
438 a[2] = c2->c[2] - c1->c[2];
439 b[0] = c3->c[0] - c1->c[0];
440 b[1] = c3->c[1] - c1->c[1];
441 b[2] = c3->c[2] - c1->c[2];
442 vecdif3f(a,c2->c,c1->c);
443 vecdif3f(b,c3->c,c1->c);
444 veccross3f(fnorm,a,b);
445 fnormlen = veclength3f(fnorm);
446 veccopy3f(facenormals[this_face].c,fnorm);
447 //facenormals[this_face].x = a[1]*b[2] - b[1]*a[2];
448 //facenormals[this_face].y = -(a[0]*b[2] - b[0]*a[2]);
449 //facenormals[this_face].z = a[0]*b[1] - b[0]*a[1];
450
451 /* printf ("vector length is %f\n",calc_vector_length (facenormals[this_face])); */
452
453 //if (APPROX(calc_vector_length (facenormals[this_face]),0.0)) {
454 if (APPROX(fnormlen,0.0f)) {
455 //printf ("warning: Tesselated surface has invalid normal - if this is an IndexedFaceSet, check coordinates of ALL faces\n");
456 } else {
457
458 //normalize_vector(&facenormals[this_face]);
459 vecnormalize3f(facenormals[this_face].c,facenormals[this_face].c);
460
461 /* printf ("vertices \t%f %f %f\n\t\t%f %f %f\n\t\t%f %f %f\n",*/
462 /* c1->c[0],c1->c[1],c1->c[2],*/
463 /* c2->c[0],c2->c[1],c2->c[2],*/
464 /* c3->c[0],c3->c[1],c3->c[2]);*/
465 //printf ("face %3d normal %5.2f %5.2f %5.2f\n",this_face,facenormals[this_face].c[0],facenormals[this_face].c[1],facenormals[this_face].c[2]);
466 /* facenormals[this_face].y,facenormals[this_face].z);*/
467 }
468}
469
470
471void add_to_face (
472 int point,
473 int face,
474 int *pointfaces) {
475
476 int count;
477 if (pointfaces[point] < (POINT_FACES-1)) {
478 /* room to add, but is it already there? */
479 for (count = 1; count <= pointfaces[point]; count++) {
480 if (pointfaces[point+count] == face) return;
481 }
482 /* ok, we have an empty slot, and face not already added */
483 pointfaces[point]++;
484 pointfaces[point+ pointfaces[point]] = face;
485 }
486}
487
488/********************************************************************
489 *
490 * ElevationGrid Triangle
491 *
492 */
493void Elev_Tri (
494 int vertex_ind,
495 int this_face,
496 int A,
497 int D,
498 int E,
499 int NONORMALS,
500 struct X3D_PolyRep *this_Elev,
501 struct SFVec3f *facenormals, //struct point_XYZ *facenormals,
502 int *pointfaces,
503 int ccw) {
504
505 struct SFVec3f *c1,*c2,*c3;
506 float a[3], b[3], fnorm[3], fnormlen;
507 int tmp;
508
509 /* printf ("Elev_Tri Triangle %d %d %d\n",A,D,E); */
510
511 /* generate normals in a clockwise manner, reverse the triangle */
512 if (!(ccw)) {
513 tmp = D;
514 D = E;
515 E = tmp;
516 }
517
518
519 this_Elev->cindex[vertex_ind] = (GLuint)A;
520 this_Elev->cindex[vertex_ind+1] = (GLuint)D;
521 this_Elev->cindex[vertex_ind+2] = (GLuint)E;
522
523 /*
524 printf ("Elev_Tri, vertices for vertex_ind %d are:",vertex_ind);
525 c1 = (struct SFVec3f *) &this_Elev->actualCoord[3*A];
526 c2 = (struct SFVec3f *) &this_Elev->actualCoord[3*D];
527 c3 = (struct SFVec3f *) &this_Elev->actualCoord[3*E];
528
529 printf ("\n%f %f %f\n%f %f %f\n%f %f %f\n\n",
530 c1->c[0], c1->c[1],c1->c[2],c2->c[0],c2->c[1],c2->c[2],
531 c3->c[0],c3->c[1],c3->c[2]);
532 */
533
534
535 if (NONORMALS) {
536 /* calculate normal for this triangle */
537 c1 = (struct SFVec3f *) &this_Elev->actualCoord[3*A];
538 c2 = (struct SFVec3f *) &this_Elev->actualCoord[3*D];
539 c3 = (struct SFVec3f *) &this_Elev->actualCoord[3*E];
540
541 /*
542 printf ("calc norms \n%f %f %f\n%f %f %f\n%f %f %f\n",
543 c1->c[0], c1->c[1],c1->c[2],c2->c[0],c2->c[1],c2->c[2],
544 c3->c[0],c3->c[1],c3->c[2]);
545 */
546
547 a[0] = c2->c[0] - c1->c[0];
548 a[1] = c2->c[1] - c1->c[1];
549 a[2] = c2->c[2] - c1->c[2];
550 b[0] = c3->c[0] - c1->c[0];
551 b[1] = c3->c[1] - c1->c[1];
552 b[2] = c3->c[2] - c1->c[2];
553 vecdif3f(a,c2->c,c1->c);
554 vecdif3f(b,c3->c,c1->c);
555 veccross3f(fnorm,a,b);
556 vecnormalize3f(fnorm,fnorm);
557 veccopy3f(facenormals[this_face].c,fnorm);
558 //facenormals[this_face].x = a[1]*b[2] - b[1]*a[2];
559 //facenormals[this_face].y = -(a[0]*b[2] - b[0]*a[2]);
560 //facenormals[this_face].z = a[0]*b[1] - b[0]*a[1];
561
562 /*
563 printf ("facenormals index %d is %f %f %f\n",this_face, facenormals[this_face].x,
564 facenormals[this_face].y, facenormals[this_face].z);
565 */
566
567 /* add this face to the faces for this point */
568 add_to_face (A*POINT_FACES,this_face,pointfaces);
569 add_to_face (D*POINT_FACES,this_face,pointfaces);
570 add_to_face (E*POINT_FACES,this_face,pointfaces);
571 }
572}
573
574
575
576/***********************************************************************8
577 *
578 * Extrusion Texture Mapping
579 *
580 ***********************************************************************/
581
582void Extru_tex(
583 int vertex_ind,
584 int tci_ct,
585 int A,
586 int B,
587 int C,
588 GLuint *tcindex,
589 int ccw,
590 int tcindexsize) {
591
592 int j;
593
594 /* bounds check */
595 /* printf ("Extru_tex, tcindexsize %d, vertex_ind %d\n",tcindexsize, vertex_ind); */
596 if (vertex_ind+2 >= tcindexsize) {
597 printf ("INTERNAL ERROR: Extru_tex, bounds check %d >= %d\n",vertex_ind+2,tcindexsize);
598 }
599
600 /* generate textures in a clockwise manner, reverse the triangle */
601 if (!(ccw)) { j = B; B = C; C = j; }
602
603 /* ok, we have to do textures; lets do the tcindexes and record min/max */
604 tcindex[vertex_ind] = (GLuint)(tci_ct+A);
605 tcindex[vertex_ind+1] =(GLuint)(tci_ct+B);
606 tcindex[vertex_ind+2] =(GLuint)(tci_ct+C);
607}
608
609
610/*********************************************************************
611 *
612 * S,T mappings for Extrusions on begin and end caps.
613 *
614 **********************************************************************/
615
616
617void Extru_ST_map(
618 int triind_start,
619 int start,
620 int end,
621 float *Vals,
622 int nsec,
623 GLuint *tcindex,
624 GLuint *cindex,
625 float *GeneratedTexCoords,
626 int tcoordsize) {
627
628 int x;
629 GLfloat minS = 9999.9f;
630 GLfloat maxS = -9999.9f;
631 GLfloat minT = 9999.9f;
632 GLfloat maxT = -9999.9f;
633
634 GLfloat Srange = 0.0f;
635 GLfloat Trange = 0.0f;
636
637 int Point_Zero; /* the point that all cap tris start at. see comment below */
638
639 /* printf ("Extru_ST, nsec %d\n",nsec); */
640
641 /* find the base and range of S, T */
642 for (x=0; x<nsec; x++) {
643 /* printf ("for textures, coord vals %f %f for sec %d\n", Vals[x*2+0], Vals[x*2+1],x); */
644 if (Vals[x*2+0] < minS) minS = Vals[x*2+0];
645 if (Vals[x*2+0] > maxS) maxS = Vals[x*2+0];
646 if (Vals[x*2+1] < minT) minT = Vals[x*2+1];
647 if (Vals[x*2+1] > maxT) maxT = Vals[x*2+1];
648 }
649 Srange = maxS -minS;
650 Trange = maxT - minT;
651
652 /* I hate divide by zeroes. :-) */
653 if (APPROX(Srange, 0.0)) Srange = 0.001f;
654 if (APPROX(Trange, 0.0)) Trange = 0.001f;
655
656 /* printf ("minS %f Srange %f minT %f Trange %f\n",minS,Srange,minT,Trange); */
657
658 /* Ok, we know the min vals of S and T; and the ranges. The way that end cap
659 * triangles are drawn is that we have one common point, the first point in
660 * each triangle. Use this as a base into the Vals index, to generate a S,T
661 * tex coord mapping for the [0,1] range
662 */
663
664 for(x=start; x<end; x++) {
665 int tci;
666 // int ci;
667
668 /*
669 printf ("Extru_ST_Map: triangle has tex vertices:%d %d %d ",
670 tcindex[triind_start*3],
671 tcindex[triind_start*3+1] ,
672 tcindex[triind_start*3+2]);
673 printf ("Extru_ST_Map: coord vertices:%d %d %d\n",
674 cindex[triind_start*3],
675 cindex[triind_start*3+1] ,
676 cindex[triind_start*3+2]);
677 */
678
679 /* for first vertex */
680 tci = tcindex[triind_start*3];
681 //ci = cindex[triind_start*3];
682 Point_Zero = tci;
683
684 if ((tci*3+2) >= tcoordsize) {
685 printf ("INTERNAL ERROR: Extru_ST_map(1), index %d greater than %d \n",(tci*3+2),tcoordsize);
686 return;
687 }
688
689 /* S value */
690 GeneratedTexCoords[tci*3+0] = (Vals[(tci-Point_Zero)*2+0] - minS) / Srange ;
691
692 /* not used by render_polyrep */
693 GeneratedTexCoords[tci*3+1] = 0;
694
695 /* T value */
696 GeneratedTexCoords[tci*3+2] = (Vals[(tci-Point_Zero)*2+1] - minT) / Trange;
697
698
699 /* for second vertex */
700 tci = tcindex[triind_start*3+1];
701 //ci = cindex[triind_start*3+1];
702
703 if ((tci*3+2) >= tcoordsize) {
704 printf ("INTERNAL ERROR: Extru_ST_map(2), index %d greater than %d \n",(tci*3+2),tcoordsize);
705 return;
706 }
707
708 /* S value */
709 GeneratedTexCoords[tci*3+0] = (Vals[(tci-Point_Zero)*2+0] - minS) / Srange ;
710
711 /* not used by render_polyrep */
712 GeneratedTexCoords[tci*3+1] = 0;
713
714 /* T value */
715 GeneratedTexCoords[tci*3+2] = (Vals[(tci-Point_Zero)*2+1] - minT) / Trange;
716
717
718 /* for third vertex */
719 tci = tcindex[triind_start*3+2];
720
721 if ((tci*3+2) >= tcoordsize) {
722 printf ("INTERNAL ERROR: Extru_ST_map(3), index %d greater than %d \n",(tci*3+2),tcoordsize);
723 return;
724 }
725
726 /* S value */
727 GeneratedTexCoords[tci*3+0] = (Vals[(tci-Point_Zero)*2+0] - minS) / Srange ;
728
729 /* not used by render_polyrep */
730 GeneratedTexCoords[tci*3+1] = 0;
731
732 /* T value */
733 GeneratedTexCoords[tci*3+2] = (Vals[(tci-Point_Zero)*2+1] - minT) / Trange;
734
735 triind_start++;
736 }
737}
738
739
740void do_glNormal3fv(struct SFVec3f *dest, GLfloat *param) {
741 struct point_XYZ myp;
742
743 /* normalize all vectors; even if they are coded into a VRML file */
744
745 myp.x = param[0]; myp.y = param[1]; myp.z = param[2];
746
747 normalize_vector (&myp);
748
749 dest->c[0] = (float) myp.x; dest->c[1] = (float) myp.y; dest->c[2] = (float) myp.z;
750}
751
752
753
754
755
756/*********************************************************************
757 *
758 * render_polyrep : render one of the internal polygonal representations
759 * for some nodes
760 *
761 ********************************************************************/
762#define DESIRE(whichOne,zzz) ((whichOne & zzz)==zzz)
763
764
765void render_polyrep(void* node) {
766 //struct X3D_Virt *virt;
767 struct X3D_Node* renderedNodePtr;
768 struct X3D_PolyRep* pr;
769 int hasc;
770
771
772 ttglobal tg = gglobal();
773
774 renderedNodePtr = X3D_NODE(node);
775 //virt = virtTable[renderedNodePtr->_nodeType];
776 pr = (struct X3D_PolyRep*) renderedNodePtr->_intern;
777
778#ifdef TEXVERBOSE
779 printf("\nrender_polyrep, _nodeType %s\n", stringNodeType(renderedNodePtr->_nodeType));
780 printf("ntri %d\n", pr->ntri);
781#endif
782
783 if (pr->ntri == 0) {
784 /* no triangles */
785 return;
786 }
787
788 // do we have VBOs here? were they removed??
789 if ((pr->VBO_buffers[VERTEX_VBO]) == 0) return;
790
791 if (!pr->streamed) {
792 printf("render_polyrep, not streamed, returning\n");
793 return;
794 }
795
796 /* save these values for streaming the texture coordinates later */
797 tg->Textures.global_tcin = pr->tcindex;
798 tg->Textures.global_tcin_count = pr->ntri * 3;
799 tg->Textures.global_tcin_lastParent = node;
800
801 /* we take the geometry here, and push it up the stream. */
802 if (0) {
803 static int count = 0;
804 if (count < 30000)
805 {
806 extent6f_printf(renderedNodePtr->_extent); printf(" r_p\n");
807 }
808 count++;
809 }
810 if (1) setExtent(renderedNodePtr->EXTENT_MAX_X, renderedNodePtr->EXTENT_MIN_X, renderedNodePtr->EXTENT_MAX_Y,
811 renderedNodePtr->EXTENT_MIN_Y, renderedNodePtr->EXTENT_MAX_Z, renderedNodePtr->EXTENT_MIN_Z,
812 renderedNodePtr);
813
814 /* clockwise or not?*/
815 if (!pr->ccw) {
816 //FW_GL_FRONTFACE(GL_CW);
817 glEnable(GL_CULL_FACE);
818 glCullFace(GL_FRONT);
819 }
820 //http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/lighting.html#t-Litcolourandalpha
821 //if lit, use colors if colornode and (intensity or no texture)
822 hasc = ((pr->VBO_buffers[COLOR_VBO] != 0) || pr->color);
823
824 /* Do we have any colours? Are textures, if present, not RGB? */
825 if (hasc) {
826 LIGHTING_ON
827 }
828
829 /* status bar, text do not have normals*/
830 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, 0);
831 if (pr->VBO_buffers[NORMAL_VBO] != 0) {
832 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, pr->VBO_buffers[NORMAL_VBO]);
833 FW_GL_NORMAL_POINTER(GL_FLOAT, 0, 0);
834 if (DESIRE(getShaderFlags().base, SHADINGSTYLE_FLAT)) {
835 if (pr->last_normal_type != 1)
836 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * pr->ntri * 3, pr->flat_normal, GL_STATIC_DRAW); /* OpenGL-ES */
837 pr->last_normal_type = 1;
838 }
839 else {
840 if (pr->last_normal_type != 0)
841 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * pr->ntri * 3, pr->normal, GL_STATIC_DRAW); /* OpenGL-ES */
842 pr->last_normal_type = 0;
843 }
844 }
845
846 if (pr->VBO_buffers[FOG_VBO] != 0) {
847 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, pr->VBO_buffers[FOG_VBO]);
848 FW_GL_FOG_POINTER(GL_FLOAT, 0, 0);
849 }
850
851 /* colours? */
852 if (hasc) {
853
854 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, pr->VBO_buffers[COLOR_VBO]);
855 FW_GL_COLOR_POINTER(4, GL_FLOAT, 0, 0);
856 }
857
858
859 /* textures?*/
860 if (pr->VBO_buffers[TEXTURE_VBO0] != 0) {
861 int k;
862 struct textureVertexInfo mtf[4] = { {NULL,2,GL_FLOAT,0, NULL,NULL},
863 {NULL,2,GL_FLOAT,0, NULL,NULL},{NULL,2,GL_FLOAT,0, NULL,NULL},{NULL,2,GL_FLOAT,0, NULL,NULL} };
864 for (k = 0; k < max(1, pr->ntcoord); k++) {
865 //FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,pr->VBO_buffers[TEXTURE_VBO0+k]);
866 mtf[k].VBO = pr->VBO_buffers[TEXTURE_VBO0 + k];
867 mtf[k].TC_size = pr->ntexdim[k];
868 if (k > 0) mtf[k - 1].next = &mtf[k];
869 }
870 textureCoord_send(mtf);
871 }
872 else {
873 ConsoleMessage("skipping tds of textures");
874 }
875 //humanoid skinning
876 if (pr->VBO_buffers[CINDEX_VBO] != 0) {
877 //PRINT_GL_ERROR_IF_ANY("BIND CINDEX 0");
878 //in child_humanoid before drawing skin we push the humanoid.coords
879 // and in here if we set the joint index VBO and joint matrix UBO
880 //printf("SKINNING ");
881 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, pr->VBO_buffers[CINDEX_VBO]);
882 //PRINT_GL_ERROR_IF_ANY("BIND CINDEX 1");
883 FW_GL_CINDEX_POINTER(GL_INT, 0, 0);
884 //PRINT_GL_ERROR_IF_ANY("BIND CINDEX 2");
885
886 }
887
888 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, pr->VBO_buffers[VERTEX_VBO]);
889 FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, pr->VBO_buffers[INDEX_VBO]);
890 FW_GL_VERTEX_POINTER(3, GL_FLOAT, 0, 0);
891
892 if (DESIRE(getShaderFlags().base, SHADINGSTYLE_WIRE)) {
893 //wireframe triangles
894 if (pr->last_index_type != 1)
895 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * pr->ntri * 3 * 2, pr->wire_indices, GL_STATIC_DRAW); /* OpenGL-ES */
896 pr->last_index_type = 1;
897 //if (setupShader())
898 // glDrawElements(GL_LINES, pr->ntri*3*2, GL_UNSIGNED_INT, NULL);
899 sendElementsToGPU(GL_LINES, pr->ntri * 3 * 2, NULL);
900 }
901 else {
902 //surface triangles
903 //glDrawArrays(GL_TRIANGLES,,,) doesn't use indices - its glDrawElements that does
904 //if(pr->last_index_type != 0)
905 // glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof (GLuint)*pr->ntri*3,pr->tri_indices,GL_STATIC_DRAW); /* OpenGL-ES */
906 pr->last_index_type = 0;
907 sendArraysToGPU(GL_TRIANGLES, 0, pr->ntri * 3);
908 }
909
910 /* turn VBOs off for now */
911 //FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, 0);
912 //FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
913
914 tg->Mainloop.trisThisLoop += pr->ntri;
915
916
917
918 PRINT_GL_ERROR_IF_ANY("");
919
920 if (!pr->ccw) {
921 //FW_GL_FRONTFACE(GL_CCW);
922 glCullFace(GL_BACK); //restore to default
923 glDisable(GL_CULL_FACE);
924 }
925
926#ifdef TEXVERBOSE
927 {
928 int i;
929 int* cin;
930 float* cod;
931 float* tcod;
932 tcod = pr->GeneratedTexCoords;
933 cod = pr->actualCoord;
934 cin = pr->cindex;
935 printf("\n\nrender_polyrep:\n");
936 for (i = 0; i < pr->ntri * 3; i++) {
937 printf("i %d cindex %d vertex %f %f %f", i, cin[i],
938 cod[cin[i] * 3 + 0],
939 cod[cin[i] * 3 + 1],
940 cod[cin[i] * 3 + 2]);
941
942 if (tcod != 0) {
943 printf(" tex %f %f",
944 tcod[cin[i] * 2 + 0],
945 tcod[cin[i] * 2 + 1]);
946 }
947 printf("\n");
948 }
949 }
950#endif
951
952 PRINT_GL_ERROR_IF_ANY("");
953
954
955}
956
957
958/*********************************************************************
959 *
960 * render_ray_polyrep : get intersections of a ray with one of the
961 * polygonal representations
962 *
963 * currently handled:
964 * rendray_Text
965 * rendray_ElevationGrid
966 * rendray_Extrusion
967 * rendray_IndexedFaceSet
968 * rendray_ElevationGrid
969 * rendray_IndexedTriangleSet
970 * rendray_IndexedTriangleFanSet
971 * rendray_IndexedTriangleStripSet
972 * rendray_TriangleSet
973 * rendray_TriangleFanSet
974 * rendray_TriangleStripSet
975 * rendray_GeoElevationGrid
976 */
977
978
979void render_ray_polyrep_A(void *node) {
980 //this doesn't work with large pick rays for geo size scenes
981 //struct X3D_Virt *virt;
982 struct X3D_Node *genericNodePtr;
983 struct X3D_PolyRep *polyRep;
984 int i;
985 int pt;
986 float *point[3];
987 struct point_XYZ v1, v2, v3;
988 //struct point_XYZ ray;
989 float pt1, pt2, pt3;
990 struct point_XYZ hitpoint;
991 float tmp1,tmp2;
992 float v1len, v2len, v3len;
993 float v12pt;
994 struct point_XYZ t_r1,t_r2;
995 //ttglobal tg;
996
997 /* is this structure still loading? */
998 if (!node) return;
999 //tg = gglobal();
1000 //VECCOPY(t_r1,tg->RenderFuncs.t_r1);
1001 //VECCOPY(t_r2,tg->RenderFuncs.t_r2);
1002 get_current_ray(&t_r1, &t_r2);
1003
1004 //VECCOPY(t_r3,tg->RenderFuncs.t_r3);
1005
1006 //ray.x = t_r2.x - t_r1.x;
1007 //ray.y = t_r2.y - t_r1.y;
1008 //ray.z = t_r2.z - t_r1.z;
1009
1010 genericNodePtr = X3D_NODE(node);
1011 //virt = virtTable[genericNodePtr->_nodeType];
1012
1013 /* is this structure still loading? */
1014 if (!(genericNodePtr->_intern)) {
1015 /* printf ("render_ray_polyrep - no internal structure, returning\n"); */
1016 return;
1017 }
1018
1019 polyRep = (struct X3D_PolyRep*) genericNodePtr->_intern;
1020 if (!polyRep->ntri || !polyRep->actualCoord) return;
1021 /*
1022 printf("render_ray_polyrep %d '%s' (%d %d): %d\n",node,stringNodeType(genericNodePtr->_nodeType),
1023 genericNodePtr->_change, polyRep->_change, polyRep->ntri);
1024 */
1025
1026
1027
1028 for(i=0; i<polyRep->ntri; i++) {
1029 for(pt = 0; pt<3; pt++) {
1030 int ind = polyRep->cindex[i*3+pt];
1031 point[pt] = (polyRep->actualCoord+3*ind);
1032 }
1033
1034 /*
1035 printf ("have points (%f %f %f) (%f %f %f) (%f %f %f)\n",
1036 point[0][0],point[0][1],point[0][2],
1037 point[1][0],point[1][1],point[1][2],
1038 point[2][0],point[2][1],point[2][2]);
1039 */
1040
1041 /* First we need to project our point to the surface */
1042 /* Poss. 1: */
1043 /* Solve s1xs2 dot ((1-r)r1 + r r2 - pt0) == 0 */
1044 /* I.e. calculate s1xs2 and ... */
1045 v1.x = point[1][0] - point[0][0];
1046 v1.y = point[1][1] - point[0][1];
1047 v1.z = point[1][2] - point[0][2];
1048 v2.x = point[2][0] - point[0][0];
1049 v2.y = point[2][1] - point[0][1];
1050 v2.z = point[2][2] - point[0][2];
1051 v1len = (float) sqrt(VECSQ(v1)); VECSCALE(v1, 1/v1len);
1052 v2len = (float) sqrt(VECSQ(v2)); VECSCALE(v2, 1/v2len);
1053 v12pt = (float) VECPT(v1,v2);
1054
1055 /* this will get around a divide by zero further on JAS */
1056 if (fabs(v12pt-1.0) < 0.00001) continue;
1057
1058 /* if we have a degenerate triangle, we can't compute a normal, so skip */
1059 if ((fabs(v1len) > 0.00001) && (fabs(v2len) > 0.00001)) {
1060
1061 /* v3 is our normal to the surface */
1062 VECCP(v1,v2,v3);
1063 v3len = (float) sqrt(VECSQ(v3)); VECSCALE(v3, 1/v3len);
1064 pt1 = (float) VECPT(t_r1,v3);
1065 pt2 = (float) VECPT(t_r2,v3);
1066 pt3 = (float) (v3.x * point[0][0] + v3.y * point[0][1] + v3.z * point[0][2]);
1067 /* Now we have (1-r)pt1 + r pt2 - pt3 = 0
1068 * r * (pt1 - pt2) = pt1 - pt3
1069 */
1070 tmp1 = pt1-pt2;
1071 if(!APPROX(tmp1,0)) {
1072 float ra, rb;
1073 float k,l;
1074 struct point_XYZ p0h;
1075
1076 tmp2 = (float) ((pt1-pt3) / (pt1-pt2));
1077 hitpoint.x = MRATX(tmp2);
1078 hitpoint.y = MRATY(tmp2);
1079 hitpoint.z = MRATZ(tmp2);
1080 /* Now we want to see if we are in the triangle */
1081 /* Projections to the two triangle sides */
1082 p0h.x = hitpoint.x - point[0][0];
1083 p0h.y = hitpoint.y - point[0][1];
1084 p0h.z = hitpoint.z - point[0][2];
1085 ra = (float) VECPT(v1, p0h);
1086 if(ra < 0.0f) {continue;}
1087 rb = (float) VECPT(v2, p0h);
1088 if(rb < 0.0f) {continue;}
1089 /* Now, the condition for the point to
1090 * be inside
1091 * (ka + lb = p)
1092 * (k + l b.a = p.a)
1093 * (k b.a + l = p.b)
1094 * (k - (b.a)**2 k = p.a - (b.a)*p.b)
1095 * k = (p.a - (b.a)*(p.b)) / (1-(b.a)**2)
1096 */
1097 k = (ra - v12pt * rb) / (1-v12pt*v12pt);
1098 l = (rb - v12pt * ra) / (1-v12pt*v12pt);
1099 k /= v1len; l /= v2len;
1100 if(k+l > 1 || k < 0 || l < 0) {
1101 continue;
1102 }
1103 rayhit(((float)(tmp2)),
1104 ((float)(hitpoint.x)),
1105 ((float)(hitpoint.y)),
1106 ((float)(hitpoint.z)),
1107 ((float)(v3.x)),
1108 ((float)(v3.y)),
1109 ((float)(v3.z)),
1110 ((float)-1),((float)-1), "polyrep");
1111 }
1112 /*
1113 } else {
1114 printf ("render_ray_polyrep, skipping degenerate triangle\n");
1115 */
1116 }
1117 }
1118}
1119
1120int triangle_intersection( float * V1, // Triangle vertices
1121 float * V2,
1122 float * V3,
1123 float * O, //Ray origin
1124 float * D, //Ray direction
1125 float* out );
1126
1127void render_ray_polyrep_B(void *node) {
1128 // this doesn't work in townsite_withHud on about the 3rd photo, can't pick in-scene hud
1129 //struct X3D_Virt *virt;
1130 struct X3D_Node *genericNodePtr;
1131 struct X3D_PolyRep *polyRep;
1132 int i;
1133 int pt;
1134 float *point[3];
1135 struct point_XYZ v1, v2, v3;
1136 double d1[3], d2[3], dO[3], dD[3];
1137 float p2[3], O[3], D[3], H[3], scale;
1138 //struct point_XYZ ray;
1139 float pt1, pt2, pt3;
1140 struct point_XYZ hitpoint;
1141 float tmp1,tmp2;
1142 float v1len, v2len, v3len;
1143 float v12pt;
1144 struct point_XYZ t_r1,t_r2;
1145 //ttglobal tg;
1146
1147 /* is this structure still loading? */
1148 if (!node) return;
1149 get_current_ray(&t_r1, &t_r2);
1150 genericNodePtr = X3D_NODE(node);
1151
1152 /* is this structure still loading? */
1153 if (!(genericNodePtr->_intern)) {
1154 /* printf ("render_ray_polyrep - no internal structure, returning\n"); */
1155 return;
1156 }
1157
1158 polyRep = (struct X3D_PolyRep*) genericNodePtr->_intern;
1159
1160 /*
1161 printf("render_ray_polyrep %d '%s' (%d %d): %d\n",node,stringNodeType(genericNodePtr->_nodeType),
1162 genericNodePtr->_change, polyRep->_change, polyRep->ntri);
1163 */
1164 //Feb 2018: we have to do some math in double, when working with geospatial or very big polyreps..
1165 pointxyz2double(dO,&t_r1);
1166 pointxyz2double(d2,&t_r2);
1167 vecdifd(dD,d2,dO);
1168 vecnormald(dD,dD);
1169
1170 //..then once we have difference vectors, we can switch to float
1171 double2float(O,dO,3);
1172 double2float(D,dD,3);
1173 /*
1174 vecprint3db("dO",dO,"\n");
1175 vecprint3db("d2",d2,"\n");
1176 vecprint3fb("O",O,"\n");
1177 vecprint3fb("D",D,"\n");
1178 */
1179 for(i=0; i<polyRep->ntri; i++) {
1180 for(pt = 0; pt<3; pt++) {
1181 int ind = polyRep->cindex[i*3+pt];
1182 point[pt] = (polyRep->actualCoord+3*ind);
1183 }
1184 if(triangle_intersection(point[0],point[1],point[2],O,D,&scale)){
1185 vecadd3f(H,O,vecscale3f(H,D,scale));
1186 rayhit(scale,
1187 H[0],
1188 H[1],
1189 H[2],
1190 0.0f,
1191 0.0f,
1192 0.0f,
1193 -1.0f,-1.0f, "polyrep2");
1194 }
1195 }
1196}
1197
1198void render_ray_polyrep(void *node) {
1199 //dug9: out of time and the picking needs a re-do
1200 // this is a hack to get it working for close range and big (geo) scenes
1201 double p1[3], p2[3], dd[3], dlength;
1202 struct point_XYZ t_r1,t_r2;
1203 get_current_ray(&t_r1, &t_r2);
1204 pointxyz2double(p1,&t_r1);
1205 //pointxyz2double(p2,&t_r2);
1206 //vecdifd(dd,p2,p1);
1207 dlength = veclengthd(p1);
1208 if(dlength > 1000.0){
1209 render_ray_polyrep_B(node);
1210 //vecprint3db("p1",p1,"");
1211 //vecprint3db("p2",p2,"\n");
1212 //printf("B");
1213 }else{
1214 render_ray_polyrep_A(node);
1215 //vecprint3db("p1",p1,"");
1216 //vecprint3db("p2",p2,"\n");
1217 //printf("A");
1218 }
1219
1220}
1221
1222// https://en.wikipedia.org/wiki/Möller–Trumbore_intersection_algorithm
1223#define EPSILON 0.000001
1224int triangle_intersection( float * V1, // Triangle vertices
1225 float * V2,
1226 float * V3,
1227 float * O, //Ray origin
1228 float * D, //Ray direction
1229 float* out ) // scale of ray direction from origin to intersection
1230{
1231 float e1[3], e2[3]; //Edge1, Edge2
1232 float P[3], Q[3], T[3];
1233 float det, inv_det, u, v;
1234 float t;
1235
1236 //Find vectors for two edges sharing V1
1237 vecdif3f(e1, V2, V1);
1238 vecdif3f(e2, V3, V1);
1239 //Begin calculating determinant - also used to calculate u parameter
1240 veccross3f(P, D, e2);
1241 //if determinant is near zero, ray lies in plane of triangle or ray is parallel to plane of triangle
1242 det = vecdot3f(e1, P);
1243 //NOT CULLING
1244 if(det > -EPSILON && det < EPSILON) return 0;
1245 inv_det = 1.f / det;
1246
1247 //calculate distance from V1 to ray origin
1248 vecdif3f(T, O, V1);
1249
1250 //Calculate u parameter and test bound
1251 u = vecdot3f(T, P) * inv_det;
1252 //The intersection lies outside of the triangle
1253 if(u < 0.f || u > 1.f) return 0;
1254
1255 //Prepare to test v parameter
1256 veccross3f(Q, T, e1);
1257
1258 //Calculate V parameter and test bound
1259 v = vecdot3f(D, Q) * inv_det;
1260 //The intersection lies outside of the triangle
1261 if(v < 0.f || u + v > 1.f) return 0;
1262
1263 t = vecdot3f(e2, Q) * inv_det;
1264
1265 if(t > EPSILON) { //ray intersection
1266 *out = t;
1267 return 1;
1268 }
1269
1270 // No hit, no win
1271 return 0;
1272}
1273
1274enum {
1275 RAYTRIALGO_DEFAULT = 1,
1276 RAYTRIALGO_MULLER = 2,
1277 //Not implemented: watertight http://jcgt.org/published/0002/01/05/paper.pdf
1278};
1279static int raytrialgo = RAYTRIALGO_MULLER;
1280int intersect_polyrep(struct X3D_Node *node, float *p1, float *p2, float *nearest, float *normal){
1281 //need a utility function like part of guts of render_ray_polyrep
1282 //everything in same coordinate system, no matrix multiplication in here
1283 //p1, p2 - 2 points forming ray, in direciton from p1 toward p2, of length p2-p1
1284 //return value:
1285 // count of intersections - can be used for inside test (odd - inside, even - outside)
1286 // nearest[3] - the intersection nearest p1
1287 // normal[3] - normal at nearest intersection
1288
1289 //struct X3D_Virt *virt;
1290 struct X3D_Node *genericNodePtr;
1291 struct X3D_PolyRep *polyRep;
1292 int i, nintersections, ihavehit;
1293 int pt;
1294 float nearestdist, delta[3];
1295 float *point[3];
1296 struct point_XYZ v1, v2, v3;
1297 //struct point_XYZ ray;
1298 float pt1, pt2, pt3;
1299 struct point_XYZ hitpoint;
1300 float tmp1,tmp2;
1301 float v1len, v2len, v3len;
1302 float v12pt;
1303 struct point_XYZ t_r1,t_r2;
1304 //ttglobal tg;
1305
1306 ihavehit = -1;
1307
1308 /* is this structure still loading? */
1309 if (!node) return 0;
1310 //tg = gglobal();
1311 //VECCOPY(t_r1,tg->RenderFuncs.t_r1);
1312 //VECCOPY(t_r2,tg->RenderFuncs.t_r2);
1313// get_current_ray(&t_r1, &t_r2);
1314 vecdif3f(delta,p2,p1);
1315 nearestdist = veclength3f(delta) + .000001f;
1316 nintersections = 0;
1317 t_r1.x = p1[0];
1318 t_r1.y = p1[1];
1319 t_r1.z = p1[2];
1320 t_r2.x = p2[0];
1321 t_r2.y = p2[1];
1322 t_r2.z = p2[2];
1323 //VECCOPY(t_r3,tg->RenderFuncs.t_r3);
1324
1325 //ray.x = t_r2.x - t_r1.x;
1326 //ray.y = t_r2.y - t_r1.y;
1327 //ray.z = t_r2.z - t_r1.z;
1328
1329 genericNodePtr = X3D_NODE(node);
1330 //virt = virtTable[genericNodePtr->_nodeType];
1331
1332 /* is this structure still loading? */
1333 if (!(genericNodePtr->_intern)) {
1334 /* printf ("render_ray_polyrep - no internal structure, returning\n"); */
1335 return 0;
1336 }
1337
1338 polyRep = (struct X3D_PolyRep*) genericNodePtr->_intern;
1339
1340 /*
1341 printf("render_ray_polyrep %d '%s' (%d %d): %d\n",node,stringNodeType(genericNodePtr->_nodeType),
1342 genericNodePtr->_change, polyRep->_change, polyRep->ntri);
1343 */
1344
1345
1346 for(i=0; i<polyRep->ntri; i++) {
1347 for(pt = 0; pt<3; pt++) {
1348 int ind = polyRep->cindex[i*3+pt];
1349 point[pt] = (polyRep->actualCoord+3*ind);
1350 }
1351 if(raytrialgo == RAYTRIALGO_MULLER){
1352 //works for particlephysics > bounded physics
1353 float tscale, d2[3],delta[3];
1354 vecdif3f(delta,p2,p1);
1355 vecnormalize3f(d2,delta); //muller takes a D normalized direction vector
1356 if(triangle_intersection(point[0],point[1],point[2],p1,d2,&tscale)){
1357 //printf("muller-trumbore intersection tascale %f nearestdist %f\n",tscale,nearestdist);
1358 nintersections++;
1359 if(tscale > 0.0f && tscale < nearestdist){
1360 //closest so far
1361 float e1[3],e2[3],nn[3],pd[3];
1362 vecscale3f(pd,d2,tscale);
1363 vecadd3f(nearest,p1,pd);
1364 //compute normal to triangle
1365 vecdif3f(e1,point[1],point[0]);
1366 vecdif3f(e2,point[2],point[0]);
1367 veccross3f(nn,e1,e2); //e2,e1 points inside, e1,e2 points outside
1368 vecnormalize3f(normal,nn);
1369 nearestdist = tscale;
1370 ihavehit = 1;
1371 }
1372 }
1373 }else if(raytrialgo == RAYTRIALGO_DEFAULT){
1374 //doesn't work right for particle physics > bounded physics
1375 //x leaks on right side of IFS box, occassionally leaky left side
1376 /*
1377 printf ("have points (%f %f %f) (%f %f %f) (%f %f %f)\n",
1378 point[0][0],point[0][1],point[0][2],
1379 point[1][0],point[1][1],point[1][2],
1380 point[2][0],point[2][1],point[2][2]);
1381 */
1382
1383 /* First we need to project our point to the surface */
1384 /* Poss. 1: */
1385 /* Solve s1xs2 dot ((1-r)r1 + r r2 - pt0) == 0 */
1386 /* I.e. calculate s1xs2 and ... */
1387 v1.x = point[1][0] - point[0][0];
1388 v1.y = point[1][1] - point[0][1];
1389 v1.z = point[1][2] - point[0][2];
1390 v2.x = point[2][0] - point[0][0];
1391 v2.y = point[2][1] - point[0][1];
1392 v2.z = point[2][2] - point[0][2];
1393 v1len = (float) sqrt(VECSQ(v1)); VECSCALE(v1, 1/v1len);
1394 v2len = (float) sqrt(VECSQ(v2)); VECSCALE(v2, 1/v2len);
1395 v12pt = (float) VECPT(v1,v2);
1396
1397 /* this will get around a divide by zero further on JAS */
1398 if (fabs(v12pt-1.0) < 0.00001)
1399 continue;
1400
1401 /* if we have a degenerate triangle, we can't compute a normal, so skip */
1402
1403 if ((fabs(v1len) > 0.00001) && (fabs(v2len) > 0.00001)) {
1404
1405 /* v3 is our normal to the surface */
1406 VECCP(v1,v2,v3);
1407 v3len = (float) sqrt(VECSQ(v3)); VECSCALE(v3, 1/v3len);
1408
1409 pt1 = (float) VECPT(t_r1,v3);
1410 pt2 = (float) VECPT(t_r2,v3);
1411 pt3 = (float) (v3.x * point[0][0] + v3.y * point[0][1] + v3.z * point[0][2]);
1412 /* Now we have (1-r)pt1 + r pt2 - pt3 = 0
1413 * r * (pt1 - pt2) = pt1 - pt3
1414 */
1415 tmp1 = pt1-pt2;
1416 if(!APPROX(tmp1,0)) {
1417 float ra, rb;
1418 float k,l;
1419 struct point_XYZ p0h;
1420
1421 tmp2 = (float) ((pt1-pt3) / (pt1-pt2));
1422 hitpoint.x = MRATX(tmp2);
1423 hitpoint.y = MRATY(tmp2);
1424 hitpoint.z = MRATZ(tmp2);
1425 /* Now we want to see if we are in the triangle */
1426 /* Projections to the two triangle sides */
1427 p0h.x = hitpoint.x - point[0][0];
1428 p0h.y = hitpoint.y - point[0][1];
1429 p0h.z = hitpoint.z - point[0][2];
1430 ra = (float) VECPT(v1, p0h);
1431 if(ra < 0.0f) {
1432 continue;
1433 }
1434 rb = (float) VECPT(v2, p0h);
1435 if(rb < 0.0f) {
1436 continue;
1437 }
1438 /* Now, the condition for the point to
1439 * be inside
1440 * (ka + lb = p)
1441 * (k + l b.a = p.a)
1442 * (k b.a + l = p.b)
1443 * (k - (b.a)**2 k = p.a - (b.a)*p.b)
1444 * k = (p.a - (b.a)*(p.b)) / (1-(b.a)**2)
1445 */
1446 k = (ra - v12pt * rb) / (1-v12pt*v12pt);
1447 l = (rb - v12pt * ra) / (1-v12pt*v12pt);
1448 k /= v1len; l /= v2len;
1449 if(k+l > 1 || k < 0 || l < 0) {
1450 continue;
1451 }
1452 //we have a hit
1453 nintersections ++;
1454 if(tmp2 >= 0.0 && tmp2 < nearestdist){
1455 ihavehit = 1;
1456 nearest[0] = (float)hitpoint.x;
1457 nearest[1] = (float)hitpoint.y;
1458 nearest[2] = (float)hitpoint.z;
1459 normal[0] = (float)v3.x;
1460 normal[1] = (float)v3.y;
1461 normal[2] = (float)v3.z;
1462 nearestdist = tmp2;
1463 }
1464 //rayhit(((float)(tmp2)),
1465 //((float)(hitpoint.x)),
1466 //((float)(hitpoint.y)),
1467 //((float)(hitpoint.z)),
1468 // ((float)(v3.x)),
1469 //((float)(v3.y)),
1470 //((float)(v3.z)),
1471 //((float)-1),((float)-1), "polyrep");
1472 }
1473 } // if degenerate
1474 } // if raytrialgo
1475 } //for triangle
1476
1477 return nintersections*ihavehit; //-ve if no hit but intersections of infinite ray for p1,
1478 // +ve if hit and intersections, 0 -nothing
1479}
1480int intersect_polyrep2(struct X3D_Node *node, float *p1, float *p2, Stack *intersection_stack){
1481 //this one returns a vector of points
1482 //please allocate intersection_stack before calling ie instersection_stack = newStack(struct intersection_info);
1483 //p1 - p2 is your plumbline or line, see also particalsystems for use
1484 //need a utility function like part of guts of render_ray_polyrep
1485 //everything in same coordinate system, no matrix multiplication in here
1486 //p1, p2 - 2 points forming ray, in direciton from p1 toward p2, of length p2-p1
1487 //return value:
1488 // count of intersections - can be used for inside test (odd - inside, even - outside)
1489 // nearest[3] - the intersection nearest p1
1490 // normal[3] - normal at nearest intersection
1491
1492 //struct X3D_Virt *virt;
1493 struct X3D_Node *genericNodePtr;
1494 struct X3D_PolyRep *polyRep;
1495 int i, nintersections, ihavehit;
1496 int pt;
1497 float nearestdist, delta[3];
1498 float *point[3];
1499 struct point_XYZ v1, v2, v3;
1500 //struct point_XYZ ray;
1501 float pt1, pt2, pt3;
1502 struct point_XYZ hitpoint;
1503 float tmp1,tmp2;
1504 float v1len, v2len, v3len;
1505 float v12pt;
1506 struct point_XYZ t_r1,t_r2;
1507 //ttglobal tg;
1508
1509 ihavehit = -1;
1510
1511 /* is this structure still loading? */
1512 if (!node) return 0;
1513 //tg = gglobal();
1514 //VECCOPY(t_r1,tg->RenderFuncs.t_r1);
1515 //VECCOPY(t_r2,tg->RenderFuncs.t_r2);
1516// get_current_ray(&t_r1, &t_r2);
1517 vecdif3f(delta,p2,p1);
1518 nearestdist = veclength3f(delta) + .000001f;
1519 nintersections = 0;
1520 t_r1.x = p1[0];
1521 t_r1.y = p1[1];
1522 t_r1.z = p1[2];
1523 t_r2.x = p2[0];
1524 t_r2.y = p2[1];
1525 t_r2.z = p2[2];
1526 //VECCOPY(t_r3,tg->RenderFuncs.t_r3);
1527
1528 //ray.x = t_r2.x - t_r1.x;
1529 //ray.y = t_r2.y - t_r1.y;
1530 //ray.z = t_r2.z - t_r1.z;
1531
1532 genericNodePtr = X3D_NODE(node);
1533 //virt = virtTable[genericNodePtr->_nodeType];
1534
1535 /* is this structure still loading? */
1536 if (!(genericNodePtr->_intern)) {
1537 /* printf ("render_ray_polyrep - no internal structure, returning\n"); */
1538 return 0;
1539 }
1540
1541 polyRep = (struct X3D_PolyRep*) genericNodePtr->_intern;
1542
1543 /*
1544 printf("render_ray_polyrep %d '%s' (%d %d): %d\n",node,stringNodeType(genericNodePtr->_nodeType),
1545 genericNodePtr->_change, polyRep->_change, polyRep->ntri);
1546 */
1547
1548
1549
1550 for(i=0; i<polyRep->ntri; i++) {
1551 for(pt = 0; pt<3; pt++) {
1552 int ind = polyRep->cindex[i*3+pt];
1553 point[pt] = (polyRep->actualCoord+3*ind);
1554 }
1555 if(raytrialgo == RAYTRIALGO_MULLER){
1556 //works for particlephysics > bounded physics
1557 float tscale, d2[3],delta[3];
1558 vecdif3f(delta,p2,p1);
1559 vecnormalize3f(d2,delta); //muller takes a D normalized direction vector
1560 if(triangle_intersection(point[0],point[1],point[2],p1,d2,&tscale)){
1561 //printf("muller-trumbore intersection tascale %f nearestdist %f\n",tscale,nearestdist);
1562 nintersections++;
1563 if(tscale > 0.0f && tscale < veclength3f(delta)){ //nearestdist){
1564 //closest so far
1565 float e1[3],e2[3],nn[3],pd[3],pi[3],normi[3];
1566 struct intersection_info iinfo;
1567 vecscale3f(pd,d2,tscale);
1568 vecadd3f(pi,p1,pd);
1569 //compute normal to triangle
1570 vecdif3f(e1,point[1],point[0]);
1571 vecdif3f(e2,point[2],point[0]);
1572 veccross3f(nn,e1,e2); //e2,e1 points inside, e1,e2 points outside
1573 vecnormalize3f(normi,nn);
1574 veccopy3f(iinfo.p,pi);
1575 veccopy3f(iinfo.normal,normi);
1576 stack_push(struct intersection_info,intersection_stack,iinfo);
1577 if(tscale < nearestdist) {
1578 //veccopy3f(nearest,pi);
1579 //veccopy3f(normal,normi);
1580 nearestdist = tscale;
1581 ihavehit = 1;
1582 }
1583 }
1584 }
1585 }else if(raytrialgo == RAYTRIALGO_DEFAULT){
1586 //doesn't work right for particle physics > bounded physics
1587 //x leaks on right side of IFS box, occassionally leaky left side
1588 /*
1589 printf ("have points (%f %f %f) (%f %f %f) (%f %f %f)\n",
1590 point[0][0],point[0][1],point[0][2],
1591 point[1][0],point[1][1],point[1][2],
1592 point[2][0],point[2][1],point[2][2]);
1593 */
1594
1595 /* First we need to project our point to the surface */
1596 /* Poss. 1: */
1597 /* Solve s1xs2 dot ((1-r)r1 + r r2 - pt0) == 0 */
1598 /* I.e. calculate s1xs2 and ... */
1599 v1.x = point[1][0] - point[0][0];
1600 v1.y = point[1][1] - point[0][1];
1601 v1.z = point[1][2] - point[0][2];
1602 v2.x = point[2][0] - point[0][0];
1603 v2.y = point[2][1] - point[0][1];
1604 v2.z = point[2][2] - point[0][2];
1605 v1len = (float) sqrt(VECSQ(v1)); VECSCALE(v1, 1/v1len);
1606 v2len = (float) sqrt(VECSQ(v2)); VECSCALE(v2, 1/v2len);
1607 v12pt = (float) VECPT(v1,v2);
1608
1609 /* this will get around a divide by zero further on JAS */
1610 if (fabs(v12pt-1.0) < 0.00001)
1611 continue;
1612
1613 /* if we have a degenerate triangle, we can't compute a normal, so skip */
1614
1615 if ((fabs(v1len) > 0.00001) && (fabs(v2len) > 0.00001)) {
1616
1617 /* v3 is our normal to the surface */
1618 VECCP(v1,v2,v3);
1619 v3len = (float) sqrt(VECSQ(v3)); VECSCALE(v3, 1/v3len);
1620
1621 pt1 = (float) VECPT(t_r1,v3);
1622 pt2 = (float) VECPT(t_r2,v3);
1623 pt3 = (float) (v3.x * point[0][0] + v3.y * point[0][1] + v3.z * point[0][2]);
1624 /* Now we have (1-r)pt1 + r pt2 - pt3 = 0
1625 * r * (pt1 - pt2) = pt1 - pt3
1626 */
1627 tmp1 = pt1-pt2;
1628 if(!APPROX(tmp1,0)) {
1629 float ra, rb;
1630 float k,l;
1631 struct point_XYZ p0h;
1632
1633 tmp2 = (float) ((pt1-pt3) / (pt1-pt2));
1634 hitpoint.x = MRATX(tmp2);
1635 hitpoint.y = MRATY(tmp2);
1636 hitpoint.z = MRATZ(tmp2);
1637 /* Now we want to see if we are in the triangle */
1638 /* Projections to the two triangle sides */
1639 p0h.x = hitpoint.x - point[0][0];
1640 p0h.y = hitpoint.y - point[0][1];
1641 p0h.z = hitpoint.z - point[0][2];
1642 ra = (float) VECPT(v1, p0h);
1643 if(ra < 0.0f) {
1644 continue;
1645 }
1646 rb = (float) VECPT(v2, p0h);
1647 if(rb < 0.0f) {
1648 continue;
1649 }
1650 /* Now, the condition for the point to
1651 * be inside
1652 * (ka + lb = p)
1653 * (k + l b.a = p.a)
1654 * (k b.a + l = p.b)
1655 * (k - (b.a)**2 k = p.a - (b.a)*p.b)
1656 * k = (p.a - (b.a)*(p.b)) / (1-(b.a)**2)
1657 */
1658 k = (ra - v12pt * rb) / (1-v12pt*v12pt);
1659 l = (rb - v12pt * ra) / (1-v12pt*v12pt);
1660 k /= v1len; l /= v2len;
1661 if(k+l > 1 || k < 0 || l < 0) {
1662 continue;
1663 }
1664 //we have a hit
1665 nintersections ++;
1666 if(tmp2 >= 0.0 && tmp2 < nearestdist){
1667 ihavehit = 1;
1668 //nearest[0] = (float)hitpoint.x;
1669 //nearest[1] = (float)hitpoint.y;
1670 //nearest[2] = (float)hitpoint.z;
1671 //normal[0] = (float)v3.x;
1672 //normal[1] = (float)v3.y;
1673 //normal[2] = (float)v3.z;
1674 nearestdist = tmp2;
1675 }
1676 //rayhit(((float)(tmp2)),
1677 //((float)(hitpoint.x)),
1678 //((float)(hitpoint.y)),
1679 //((float)(hitpoint.z)),
1680 // ((float)(v3.x)),
1681 //((float)(v3.y)),
1682 //((float)(v3.z)),
1683 //((float)-1),((float)-1), "polyrep");
1684 }
1685 } // if degenerate
1686 } // if raytrialgo
1687 } //for triangle
1688
1689 return nintersections*ihavehit; //-ve if no hit but intersections of infinite ray for p1,
1690 // +ve if hit and intersections, 0 -nothing
1691}
1692
1693int getPolyrepTriangleCount(struct X3D_Node *node){
1694 int iret;
1695 iret = 0;
1696 if(node->_intern){
1697 struct X3D_PolyRep *polyrep = (struct X3D_PolyRep *)node->_intern;
1698 iret = polyrep->ntri;
1699 }
1700 return iret;
1701}
1702int getPolyrepTriangleByIndex(struct X3D_Node *node, int index, float *v1, float *v2, float *v3){
1703 int iret;
1704 iret = 0;
1705 if(node->_intern){
1706 struct X3D_PolyRep *polyrep = (struct X3D_PolyRep *)node->_intern;
1707 veccopy3f(v1,&polyrep->actualCoord[(index*3 + 0)*3]);
1708 veccopy3f(v2,&polyrep->actualCoord[(index*3 + 1)*3]);
1709 veccopy3f(v3,&polyrep->actualCoord[(index*3 + 2)*3]);
1710 }
1711 return iret;
1712
1713}
1714
1715/* make the internal polyrep structure - this will contain the actual RUNTIME parameters for OpenGL */
1716void compile_polyrep(void *innode, void *coord, void *fogCoord, void *color, void *normal, struct X3D_TextureCoordinate *texCoord) {
1717 struct X3D_Virt *virt;
1718 struct X3D_Node *node;
1719 struct X3D_PolyRep *polyrep;
1720
1721 //printf ("compile_polyrep, innode %p coord %p color %p normal %p texCoord %p\n",innode,coord,color,normal,texCoord);
1722
1723 node = X3D_NODE(innode);
1724 virt = virtTable[node->_nodeType];
1725
1726 /* first time through; make the intern structure for this polyrep node */
1727 if(!node->_intern) {
1728
1729 int i;
1730
1731 node->_intern = MALLOC(struct X3D_GeomRep *, sizeof(struct X3D_PolyRep));
1732 memset(node->_intern,0,sizeof(struct X3D_PolyRep));
1733 polyrep = (struct X3D_PolyRep*) node->_intern;
1734 polyrep->itype = 2; //0 points 1 lines 2 mesh
1735 polyrep->mode = 4; //4 TRIANGLES 5 TRIANGLE_STRIP 6 TRIANGLE_FAN
1736 polyrep->ntri = -1;
1737 //polyrep->cindex = 0; polyrep->actualCoord = 0; polyrep->colindex = 0; polyrep->color = 0;
1738 //polyrep->norindex = 0; polyrep->normal = 0; polyrep->flat_normal = 0; polyrep->GeneratedTexCoords = 0;
1739 //polyrep->tri_indices = 0; polyrep->wire_indices = 0; polyrep->actualFog = 0;
1740 //polyrep->tcindex = 0;
1741 //polyrep->tcoordtype = 0;
1742 polyrep->streamed = FALSE;
1743 //polyrep->last_index_type = 0; polyrep->last_normal_type = 0;
1744
1745
1746 /* for Collision, default texture generation */
1747 polyrep->minVals[0] = 999999.9f;
1748 polyrep->minVals[1] = 999999.9f;
1749 polyrep->minVals[2] = 999999.9f;
1750 polyrep->maxVals[0] = -999999.9f;
1751 polyrep->maxVals[1] = -999999.9f;
1752 polyrep->maxVals[2] = -999999.9f;
1753
1754 for (i=0; i<VBO_COUNT; i++)
1755 polyrep->VBO_buffers[i] = 0;
1756
1757 /* printf ("generating buffers for node %p, type %s\n",p,stringNodeType(p->_nodeType)); */
1758 glGenBuffers(1,&polyrep->VBO_buffers[VERTEX_VBO]);
1759 glGenBuffers(1,&polyrep->VBO_buffers[INDEX_VBO]);
1760
1761 /* printf ("they are %u %u %u %u\n",polyrep->VBO_buffers[0],polyrep->VBO_buffers[1],polyrep->VBO_buffers[2],polyrep->VBO_buffers[3]); */
1762
1763 }
1764
1765 polyrep = (struct X3D_PolyRep*) node->_intern;
1766 polyrep->coordinate_node = coord; //for testing if skinning elsewhere
1767
1768 /* Android, for instance, needs the VBO_buffers re-created. Check to see if this is the case here */
1769 if (polyrep->VBO_buffers[VERTEX_VBO] == 0) {
1770 //ConsoleMessage ("re-creating VERTEX VBOs");
1771 glGenBuffers(1,&polyrep->VBO_buffers[VERTEX_VBO]);
1772 glGenBuffers(1,&polyrep->VBO_buffers[INDEX_VBO]);
1773 }
1774
1775 /* if multithreading, tell the rendering loop that we are regenning this one */
1776 /* if singlethreading, this'll be set to TRUE before it is tested */
1777 polyrep->streamed = FALSE;
1778
1779 FREE_IF_NZ(polyrep->cindex);
1780 FREE_IF_NZ(polyrep->actualCoord);
1781 FREE_IF_NZ(polyrep->GeneratedTexCoords[0]);
1782 FREE_IF_NZ(polyrep->colindex);
1783 FREE_IF_NZ(polyrep->color);
1784 FREE_IF_NZ(polyrep->norindex);
1785 FREE_IF_NZ(polyrep->normal);
1786 FREE_IF_NZ(polyrep->flat_normal);
1787 FREE_IF_NZ(polyrep->tcindex);
1788
1789
1790 /* make the node by calling the correct method see GenPolyRep.c > make_genericfaceset */
1791 virt->mkpolyrep(node);
1792
1793 /* now, put the generic internal structure into OpenGL arrays for faster rendering */
1794 /* if there were errors, then rep->ntri should be 0 */
1795 if (polyrep->ntri != 0) {
1796 //float *fogCoord = NULL;
1797 stream_polyrep(node, coord, fogCoord, color, normal, texCoord);
1798 /* and, tell the rendering process that this shape is now compiled */
1799 }
1800 //else wait for set_coordIndex to be converted to coordIndex
1801 polyrep->irep_change = node->_change;
1802
1803}
1804
1805void delete_geomrep(struct X3D_Node *node){
1806 // see if node has _intern, if so it's live scenery
1807 // delete opengl buffers used by polyrep
1808 // delete internal malloced items in polyrep
1809 // delete polyrep
1810 // null node's _intern field
1811 if(!node) return;
1812 if (!node->_intern) return;
1813 // 0 PointRep 1 LineRep 2 PolyRep 3 MeshRep 4 TextureRep 5 LightRep
1814 switch(node->_intern->itype){
1815 case 0: //points
1816 {
1817 if (node->_nodeType != NODE_PointSet && node->_nodeType != NODE_Polypoint2D) {
1818 printf("attempting to delete PointRep for nodetype %s\n", stringNodeType(node->_nodeType));
1819 break;
1820 }
1821 delete_PointRep(node->_intern);
1822 node->_intern = NULL;
1823 }
1824 break;
1825 case 1: //lines
1826 {
1827 struct X3D_LineRep* lr;
1828 lr = (struct X3D_LineRep*)node->_intern;
1829 //not implemented yet
1830 }
1831 break;
1832 case 2: //mesh
1833 {
1834 struct X3D_PolyRep* pr;
1835 pr = (struct X3D_PolyRep*)node->_intern;
1836 // ? apr 2015 I think the node->_intern = polyrep will only be populated
1837 // in the case of live scenery, not in ProtoDeclares, so if we are in here,
1838 // we should have live scenery, and that means gl buffers were assigned
1839 glDeleteBuffers(VBO_COUNT, pr->VBO_buffers);
1840
1841 /* indicies for arrays. OpenGL ES 2.0 - unsigned short for the DrawArrays call */
1842 FREE_IF_NZ(pr->cindex); /* triples (per triangle) */
1843 FREE_IF_NZ(pr->colindex); /* triples (per triangle) */
1844 FREE_IF_NZ(pr->norindex);
1845 FREE_IF_NZ(pr->tcindex); /* triples or null */
1846 FREE_IF_NZ(pr->tri_indices);
1847 FREE_IF_NZ(pr->wire_indices);
1848 FREE_IF_NZ(pr->actualCoord); /* triples (per point) */
1849 FREE_IF_NZ(pr->actualFog); /* float (per point) */
1850 FREE_IF_NZ(pr->color); /* triples or null */
1851 FREE_IF_NZ(pr->normal); /* triples or null */
1852 FREE_IF_NZ(pr->flat_normal);
1853 FREE_IF_NZ(pr->GeneratedTexCoords[0]); /* triples (per triangle) of texture coords if there is no texCoord node */
1854 FREE_IF_NZ(pr);
1855 node->_intern = NULL;
1856 }
1857 break;
1858 case 3: //MeshRep for gltf_loader.c
1859 {
1860 if (node->_nodeType != NODE_BufferGeometry) {
1861 printf("attempting to delete MeshRep for nodetype %s\n", stringNodeType(node->_nodeType));
1862 break;
1863 }
1864 delete_MeshRep(node->_intern);
1865 node->_intern = NULL;
1866
1867 }
1868 break;
1869 case 5: //LightRep
1870 {
1871 delete_LightRep(node->_intern);
1872 node->_intern = NULL;
1873 }
1874 case 9: //HanimRep
1875 {
1876 delete_HanimRep(node->_intern);
1877 node->_intern = NULL;
1878 }
1879 default:
1880 break;
1881 }
1882};