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