FreeWRL / FreeX3D 4.3.0
GenPolyRep.c
1/*
2
3
4???
5
6*/
7
8
9/****************************************************************************
10 This file is part of the FreeWRL/FreeX3D Distribution.
11
12 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
13
14 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
15 it under the terms of the GNU Lesser Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
26****************************************************************************/
27
28
29
30#include <config.h>
31#include <system.h>
32#include <display.h>
33#include <internal.h>
34
35#include <libFreeWRL.h>
36
37#include "../vrml_parser/Structs.h"
38#include "../vrml_parser/CRoutes.h"
39#include "../main/headers.h"
40
41#include "LinearAlgebra.h"
42#include "Polyrep.h"
43#include "Tess.h"
44#include "Component_Geospatial.h" /* resolving implicit declarations */
45
46/*****************************************
47 *
48 * Complex Geometry; ElevationGrid, Extrusion, IndexedFaceSet, Text.
49 *
50 * This code generates a Polyrep structure, that is further
51 * streamlined then streamed to OpenGL.
52 *
53 * Polyreps are streamed in Polyrep.c
54 *
55 *******************************************/
56
57//extern void Elev_Tri (int vertex_ind,int this_face,int A,int D,int E,int NONORMALS,struct X3D_PolyRep *this_Elev,struct point_XYZ *facenormals,int *pointfaces,int ccw);
58extern void Elev_Tri (int vertex_ind,int this_face,int A,int D,int E,int NONORMALS,struct X3D_PolyRep *this_Elev,struct SFVec3f *facenormals,int *pointfaces,int ccw);
59extern void verify_global_IFS_Coords(int max);
60//extern void Extru_check_normal(struct point_XYZ *facenormals,int this_face,int dire,struct X3D_PolyRep *rep_,int ccw);
61extern void Extru_check_normal(struct SFVec3f *facenormals,int this_face,int dire,struct X3D_PolyRep *rep_,int ccw);
62//void register_Polyrep_combiner();
63/* calculate how many triangles are required for IndexedTriangleFanSet and
64 IndexedTriangleStripSets */
65static int returnIndexedFanStripIndexSize (struct Multi_Int32 index ) {
66 int IndexSize;
67 int xx, zz;
68 IndexSize = 0;
69 xx = 0;
70 zz = 0;
71
72 for (xx=0; xx<index.n; xx++) {
73 /* printf ("looking at index %d, is %d of %d\n",xx,index.p[xx],index.n); */
74 if ((index.p[xx] <=-1) || (xx == (index.n-1))) {
75 /* printf ("found an end of run at %d\n",xx); */
76
77 /* are we on the last index, and it is not a -1? */
78 if ((index.p[xx] > -1) && (xx == (index.n-1))) {
79 zz++; /* include this index */
80 }
81
82 IndexSize += (zz-2) *4;
83 /* bounds checking... */
84 if (zz < 3) {
85 printf ("IndexedTriangle[Fan|Strip]Set, index %d is less than 3\n",zz);
86 return 0;
87 }
88 zz = 0;
89 } else {
90 zz++;
91 }
92 }
93
94 /* printf ("ITFS, IndexSize %d\n",IndexSize); */
95 return IndexSize;
96}
97
98/* check validity of fields */
99int checkX3DIndexedFaceSetFields (struct X3D_IndexedFaceSet *this_) {
100 /* does this have any coordinates? */
101 if (this_->coord == 0) {
102 #ifdef VERBOSE
103 printf ("checkX3DIFS - have an IFS (%d) with no coords...\n",this_);
104 #endif
105 return FALSE;
106 }
107 if (this_->coordIndex.n == 0) {
108 #ifdef VERBOSE
109 printf ("checkX3DIFS - have an IFS (%d) with no coordIndex, pointer is %d offset is %d\n",this_,
110 this_->coordIndex.p,offsetof (struct X3D_IndexedFaceSet, coordIndex));
111 #endif
112 return FALSE;
113 }
114 return TRUE;
115}
116
117/* check validity of ElevationGrid fields */
118int checkX3DElevationGridFields (struct X3D_ElevationGrid *this_, float **points, int *npoints) {
119 int i,j;
120 int nx = (this_->xDimension);
121 float xSp = (this_->xSpacing);
122 int nz = (this_->zDimension);
123 float zSp = (this_->zSpacing);
124 float *height = ((this_->height).p);
125 int ntri = (nx && nz ? 2 * (nx-1) * (nz-1) : 0);
126 int nh = ((this_->height).n);
127 struct X3D_PolyRep *rep = (struct X3D_PolyRep*) this_->_intern;
128
129 float *newpoints;
130 float newPoint[3];
131 int nquads = ntri/2;
132 int *cindexptr;
133
134 float *tcoord = NULL;
135
136 /* check validity of input fields */
137 if(nh != nx * nz) {
138 if (nh > nx * nz) {
139 printf ("Elevationgrid: warning: x,y vs. height: %d * %d ne %d:\n", nx,nz,nh);
140 } else {
141 printf ("Elevationgrid: error: x,y vs. height: %d * %d ne %d:\n", nx,nz,nh);
142 return FALSE;
143 }
144 }
145
146 /* do we have any triangles? */
147 if ((nx < 2) || (nz < 2)) {
148 printf ("ElevationGrid: xDimension and zDimension less than 2 %d %d\n", nx,nz);
149 return FALSE;
150 }
151
152 /* any texture coordinates passed in? if so, DO NOT generate any texture coords here. */
153 if (!(this_->texCoord)) {
154 /* allocate memory for texture coords */
155 FREE_IF_NZ(rep->GeneratedTexCoords[0]);
156
157 /* 6 vertices per quad each vertex has a 2-float tex coord mapping */
158 tcoord = rep->GeneratedTexCoords[0] = MALLOC (float *, sizeof (float) * nquads * 12);
159
160 rep->tcindex=0; /* we will generate our own mapping */
161 } else {
162 ConsoleMessage ("even though we have a texCoord node here, we need to generate");
163 }
164
165 /* make up points array */
166 /* a point is a vertex and consists of 3 floats (x,y,z) */
167 newpoints = MALLOC (float *, sizeof (float) * nz * nx * 3);
168
169 FREE_IF_NZ(rep->actualCoord);
170 rep->actualCoord = (float *)newpoints;
171
172 /* make up coord index */
173 if (this_->_coordIndex.n > 0) {FREE_IF_NZ(this_->_coordIndex.p);}
174 this_->_coordIndex.p = MALLOC (int *, sizeof(int) * nquads * 5);
175 cindexptr = this_->_coordIndex.p;
176
177 this_->_coordIndex.n = nquads * 5;
178 /* return the newpoints array to the caller */
179 *points = newpoints;
180 *npoints = this_->_coordIndex.n;
181
182 for (j = 0; j < (nz -1); j++) {
183 for (i=0; i < (nx-1) ; i++) {
184 /*
185 printf ("coord maker, j %d i %d\n",j,i);
186 printf ("coords for this quad: %d %d %d %d %d\n",
187 j*nx+i, j*nx+i+nx, j*nx+i+nx+1, j*nx+i+1, -1);
188 */
189
190 *cindexptr = j*nx+i; cindexptr++;
191 *cindexptr = j*nx+i+nx; cindexptr++;
192 *cindexptr = j*nx+i+nx+1; cindexptr++;
193 *cindexptr = j*nx+i+1; cindexptr++;
194 *cindexptr = -1; cindexptr++;
195
196 }
197 }
198
199 /* tex coords These need to be streamed now; that means for each quad, each vertex needs its tex coords. */
200 /* if the texCoord node exists, let render_TextureCoordinate (or whatever the node is) do our work for us */
201 if (!(this_->texCoord)) {
202 for (j = 0; j < (nz -1); j++) {
203 for (i=0; i < (nx-1) ; i++) {
204 /* first triangle, 3 vertexes */
205 /* first tri */
206 *tcoord = ((float) (i+0)/(nx-1)); tcoord++;
207 *tcoord = ((float)(j+0)/(nz-1)); tcoord ++;
208
209 *tcoord = ((float) (i+0)/(nx-1)); tcoord++;
210 *tcoord = ((float)(j+1)/(nz-1)); tcoord ++;
211
212 *tcoord = ((float) (i+1)/(nx-1)); tcoord++;
213 *tcoord = ((float)(j+1)/(nz-1)); tcoord ++;
214
215 /* second tri */
216 *tcoord = ((float) (i+0)/(nx-1)); tcoord++;
217 *tcoord = ((float)(j+0)/(nz-1)); tcoord ++;
218
219 *tcoord = ((float) (i+1)/(nx-1)); tcoord++;
220 *tcoord = ((float)(j+1)/(nz-1)); tcoord ++;
221
222 *tcoord = ((float) (i+1)/(nx-1)); tcoord++;
223 *tcoord = ((float)(j+0)/(nz-1)); tcoord ++;
224 }
225 }
226 }
227
228 /* Render_Polyrep will use this number of triangles */
229 rep->ntri = ntri;
230
231 for (j=0; j<nz; j++) {
232 for (i=0; i < nx; i++) {
233
234 /*
235 printf ("point [%d,%d] is %f %f %f (hei ind %d)\n",
236 i,j,
237 xSp * i,
238 height[i+(j*nx)],
239 zSp * j,
240 i+(j*nx));
241 */
242
243
244 newPoint[0] = xSp * i; newPoint[1] = height[i+(j*nx)]; newPoint[2]=zSp*j;
245 memcpy(newpoints,newPoint,sizeof(float)*3);
246 newpoints += 3;
247 }
248 }
249
250 return TRUE;
251}
252
253
254static void checkIndexedTriangleStripSetFields (struct X3D_IndexedTriangleStripSet *node) {
255 int IndexSize = 0;
256 int xx,yy,zz; /* temporary variables */
257 int fanVertex;
258 int *newIndex;
259 int windingOrder; /*TriangleStripSet ordering */
260
261 /* printf ("start of ITSS\n"); */
262 IndexSize = returnIndexedFanStripIndexSize(node->index);
263 if (IndexSize == 0) {
264 /* printf ("IndexSize for ITFS %d\n",IndexSize); */
265 node->index.n = 0;
266 }
267
268 newIndex = MALLOC (int *, sizeof(int) * IndexSize);
269
270 /* now calculate the indexes */
271 xx=0;
272 yy=0; zz = 0;
273 while (xx < (node->index.n-1)) {
274 fanVertex = xx;
275 /* scan forward to find end of fan */
276 while ((xx<node->index.n) && (node->index.p[xx] > -1)) xx++;
277 /* printf ("strip runs between %d and %d\n", fanVertex,xx); */
278
279 /* bounds checking... */
280 if (xx >= IndexSize) {
281 printf ("ITFS - index size error... IndexSize < index value \n");
282 xx = IndexSize;
283 }
284
285
286 windingOrder=0;
287 for (zz=fanVertex; zz<(xx-2); zz++) {
288 if (windingOrder==0) {
289 newIndex[yy] = node->index.p[zz]; yy++;
290 newIndex[yy] = node->index.p[zz+1]; yy++;
291 newIndex[yy] = node->index.p[zz+2]; yy++;
292 windingOrder ++;
293 } else {
294 newIndex[yy] = node->index.p[zz]; yy++;
295 newIndex[yy] = node->index.p[zz+2]; yy++;
296 newIndex[yy] = node->index.p[zz+1]; yy++;
297 windingOrder =0;
298 }
299 newIndex[yy] = -1; yy++;
300 }
301
302 /* is this the end of the fan? */
303 if (xx < (node->index.n-1)) {
304 xx++; /* skip past the -1 */
305 fanVertex = xx;
306 /* printf ("end of fan, but not end of structure - fanVertex %d, xx %d yy %d\n",fanVertex,xx,yy); */
307 }
308 zz += 2;
309 }
310
311 /* xx=0; while (xx < IndexSize) { printf ("index %d val %d\n",xx,newIndex[xx]); xx++; } */
312
313 /* now, make the new index active */
314 /* FREE_IF_NZ (node->coordIndex.p); should free if MALLOC'd already */
315 node->_coordIndex.p = newIndex;
316 node->_coordIndex.n = IndexSize;
317}
318
319static void checkIndexedTriangleFanSetFields (struct X3D_IndexedTriangleFanSet *node) {
320 int IndexSize = 0;
321 int xx,yy,zz; /* temporary variables */
322 int fanVertex;
323 int *newIndex;
324
325 /* printf ("start of ITFS\n"); */
326 IndexSize = returnIndexedFanStripIndexSize(node->index);
327 if (IndexSize == 0) {
328 /* printf ("IndexSize for ITFS %d\n",IndexSize); */
329 node->index.n = 0;
330 }
331
332 newIndex = MALLOC (int *, sizeof(int) * IndexSize);
333 /* now calculate the indexes */
334
335 xx=0;
336 yy=0;
337 while (xx < (node->index.n-1)) {
338 fanVertex = xx;
339 /* scan forward to find end of fan */
340 while ((xx<node->index.n) && (node->index.p[xx] > -1)) xx++;
341 /* printf ("fan runs between %d and %d\n", fanVertex,xx); */
342
343 /* bounds checking... */
344 if (xx >= IndexSize) {
345 printf ("ITFS - index size error... IndexSize < index value \n");
346 xx = IndexSize;
347 }
348
349 for (zz=fanVertex+1; zz<(xx-1); zz++) {
350 /* printf ("newIndexSize %d, fv %d, zz %d\n",IndexSize, fanVertex, zz); */
351 newIndex[yy] = node->index.p[fanVertex]; yy++;
352 newIndex[yy] = node->index.p[zz]; yy++;
353 newIndex[yy] = node->index.p[zz+1]; yy++;
354 newIndex[yy] = -1; yy++;
355 }
356
357 /* is this the end of the fan? */
358 if (xx < (node->index.n-1)) {
359 xx++; /* skip past the -1 */
360 fanVertex = xx;
361 /* printf ("end of fan, but not end of structure - fanVertex %d, xx %d yy %d\n",fanVertex,xx,yy); */
362 }
363 }
364
365 /* xx=0; while (xx < IndexSize) { printf ("index %d val %d\n",xx,newIndex[xx]); xx++; } */
366
367 /* now, make the new index active */
368 /* FREE_IF_NZ (node->coordIndex.p); should free if MALLOC'd already */
369 node->_coordIndex.p = newIndex;
370 node->_coordIndex.n = IndexSize;
371}
372
373
374static void checkIndexedTriangleSetFields (struct X3D_IndexedTriangleSet *node) {
375 int IndexSize = 0;
376 int xx,yy,zz; /* temporary variables */
377 int *newIndex;
378
379 IndexSize = ((node->index.n) * 4) / 3;
380 if (IndexSize <= 0) {
381 /* nothing to do here */
382 node->index.n = 0;
383 }
384
385 newIndex = MALLOC (int *, sizeof(int) * IndexSize);
386 zz = 0; yy=0;
387 /* printf ("index: "); */
388 for (xx = 0; xx < node->index.n; xx++) {
389 newIndex[zz] = node->index.p[xx];
390 /* printf (" %d ",newIndex[zz]); */
391 zz++;
392 yy++;
393 if (yy == 3) {
394 /* end of one triangle, put a -1 in there */
395 newIndex[zz] = -1;
396 /* printf (" -1 "); */
397 zz++;
398 yy = 0;
399 }
400 /* printf ("\n"); */
401 }
402
403 /* now, make the new index active */
404 /* FREE_IF_NZ (node->coordIndex.p); should free if MALLOC'd already */
405 node->_coordIndex.p = newIndex;
406 node->_coordIndex.n = IndexSize;
407}
408
409static void checkTriangleFanSetFields (struct X3D_TriangleFanSet *node) {
410 int IndexSize = 0;
411 int xx,yy,zz; /* temporary variables */
412 int fanVertex;
413
414 /* printf ("TFS, fanCount %d\n",(node->fanCount).n); */
415 if ((node->fanCount).n < 1) {
416 ConsoleMessage("TriangleFanSet, need at least one fanCount element");
417 node->fanCount.n = 0;
418 }
419
420 /* calculate the size of the Index array */
421 for (xx=0; xx<(node->fanCount).n; xx++) {
422 /* printf ("fanCount %d is %d \n",xx,(node->fanCount).p[xx]); */
423 IndexSize += ((node->fanCount).p[xx]-2) * 4;
424 /* bounds checking... */
425 if ((node->fanCount).p[xx] < 3) {
426 printf ("TriangleFanSet, fanCount index %d is less than 3\n", (node->fanCount).p[xx]);
427 }
428 }
429
430 /* printf ("IndexSize is %d\n",IndexSize); */
431 node->_coordIndex.p = MALLOC (int *, sizeof(int) * IndexSize);
432 node->_coordIndex.n = IndexSize;
433 IndexSize = 0; /* for assigning the indexes */
434
435 /* now calculate the indexes */
436 yy=0; zz=0;
437 for (xx=0; xx<(node->fanCount).n; xx++) {
438 /* printf ("fanCount %d is %d \n",xx,(node->fanCount).p[xx]); */
439 fanVertex = zz;
440 zz ++;
441 for (yy=0; yy< ((node->fanCount).p[xx]-2); yy++) {
442 /* printf ("fc %d tris %d %d %d -1\n",
443 xx, fanVertex, zz, zz+1); */
444 node->_coordIndex.p[IndexSize++] = fanVertex;
445 node->_coordIndex.p[IndexSize++] = zz;
446 node->_coordIndex.p[IndexSize++] = zz+1;
447 node->_coordIndex.p[IndexSize++] = -1;
448 zz++;
449 }
450 zz++;
451 }
452}
453
454static void checkIndexedQuadSetFields (struct X3D_IndexedQuadSet *node) {
455 int IndexSize = 0;
456 int xx,yy; /* temporary variables */
457 int *newIndex;
458 int *newIndexPtr;
459
460 IndexSize = ((node->index.n) /4) * 4;
461 if (IndexSize <= 0) {
462 /* nothing to do here */
463 node->index.n = 0;
464 }
465
466 //ConsoleMessage ("IndexedQuadCount = IndexSize %d from %d",IndexSize,node->index.n);
467 // do we have not enough indexes to make a quad - ie, any spare indexes?
468 if (IndexSize != node->index.n) ConsoleMessage ("IndexedQuadSet using %d of %d indexes according to spec",IndexSize,node->index.n);
469
470 // each quad is made of 5 indexes, from 4 - quad 0,1,2,3 makes 0,1,2, 3, -1
471 // as we make this into an IndexedFaceSet, with each Quad being a "face"
472
473 newIndex = MALLOC (int *, sizeof(int) * IndexSize * 5 / 4);
474 newIndexPtr = newIndex;
475 yy=0;
476 /* printf ("index: "); */
477 for (xx = 0; xx < IndexSize; xx++) {
478 *newIndexPtr = node->index.p[xx];
479
480
481 /* printf (" %d ",newIndex[zz]); */
482 newIndexPtr++;
483 yy++;
484 if (yy == 4) {
485 /* end of one triangle, put a -1 in there */
486 *newIndexPtr = -1;
487 /* printf (" -1 "); */
488 newIndexPtr++;
489 yy = 0;
490 }
491 /* printf ("\n"); */
492 }
493
494 /* now, make the new index active */
495 FREE_IF_NZ (node->index.p); /* should free if MALLOC'd already */
496 node->_coordIndex.p = newIndex;
497 node->_coordIndex.n = IndexSize * 5 / 4;
498}
499
500static void checkQuadSetFields(struct X3D_QuadSet *node) {
501 int npoints = 0;
502 int IndexSize = 0;
503 int xx; /* temporary variables */
504
505 if(node->coord) {
506 struct Multi_Vec3f *dtmp;
507 dtmp = getCoordinate (node->coord, "QuadSet");
508 npoints = dtmp->n;
509 }
510
511 /* verify whether we have an incorrect number of coords or not */
512 if (((npoints/4)*4) != npoints) {
513 ConsoleMessage ("Warning, in QuadSet, Coordinates not a multiple of 4\n");
514 npoints = ((npoints/4)*4);
515 }
516
517 /* printf ("npoints %d\n",npoints); */
518
519
520 /* calculate index size; every "face" ends in -1 */
521 IndexSize = (npoints * 8) / 4;
522 //printf ("IndexSize is %d\n",IndexSize);
523 node->_coordIndex.p = MALLOC (int *, sizeof(int) * IndexSize);
524 node->_coordIndex.n = IndexSize;
525
526 IndexSize = 0; /* for assigning the indexes */
527
528 /* now calculate the indexes */
529 for (xx=0; xx<npoints; xx+=4) {
530 /* printf ("index %d tris %d %d %d -1\n", xx/3, xx, xx+1, xx+2); */
531 node->_coordIndex.p[IndexSize++] = xx;
532 node->_coordIndex.p[IndexSize++] = xx+1;
533 node->_coordIndex.p[IndexSize++] = xx+2;
534 node->_coordIndex.p[IndexSize++] = -1;
535 node->_coordIndex.p[IndexSize++] = xx+2;
536 node->_coordIndex.p[IndexSize++] = xx+3;
537 node->_coordIndex.p[IndexSize++] = xx;
538 node->_coordIndex.p[IndexSize++] = -1;
539 }
540/* ConsoleMessage ("end of loop, index size is %d",IndexSize);
541 for (xx=0; xx<IndexSize; xx++) {
542 ConsoleMessage ("... index %d is %d\n",xx,node->_coordIndex.p[xx]);
543 }
544 */
545}
546
547
548static void checkTriangleStripSetFields (struct X3D_TriangleStripSet *node) {
549 int IndexSize = 0;
550 int xx,yy,zz; /* temporary variables */
551 int windingOrder; /*TriangleStripSet ordering */
552
553 /* printf ("TSS, stripCount %d\n",(node->stripCount).n); */
554 if ((node->stripCount).n < 1) {
555 ConsoleMessage ("TriangleStripSet, need at least one stripCount element");
556 node->stripCount.n=0;
557 }
558
559 /* calculate the size of the Index array */
560 for (xx=0; xx<(node->stripCount).n; xx++) {
561 /* printf ("stripCount %d is %d \n",xx,(node->stripCount).p[xx]); */
562 IndexSize += ((node->stripCount).p[xx]-2) * 4;
563 /* bounds checking... */
564 if ((node->stripCount).p[xx] < 3) {
565 printf ("TriangleStripSet, index %d is less than 3\n",
566 (node->stripCount).p[xx]);
567 }
568 }
569
570 /* printf ("IndexSize is %d\n",IndexSize); */
571 node->_coordIndex.p = MALLOC (int *, sizeof(int) * IndexSize);
572 node->_coordIndex.n = IndexSize;
573 IndexSize = 0; /* for assigning the indexes */
574
575 /* now calculate the indexes */
576 yy=0; zz=0;
577 for (xx=0; xx<(node->stripCount).n; xx++) {
578 windingOrder=0;
579 /* printf ("stripCount %d is %d \n",xx,(node->stripCount).p[xx]); */
580 for (yy=0; yy< ((node->stripCount).p[xx]-2); yy++) {
581 if (windingOrder==0) {
582 /* printf ("fcwo0 %d tris %d %d %d -1\n", xx, zz, zz+1, zz+2); */
583 node->_coordIndex.p[IndexSize++] = zz;
584 node->_coordIndex.p[IndexSize++] = zz+1;
585 node->_coordIndex.p[IndexSize++] = zz+2;
586 windingOrder++;
587 } else {
588 /* printf ("fcwo1 %d tris %d %d %d -1\n", xx, zz+1, zz, zz+2); */
589 node->_coordIndex.p[IndexSize++] = zz+1;
590 node->_coordIndex.p[IndexSize++] = zz;
591 node->_coordIndex.p[IndexSize++] = zz+2;
592 windingOrder=0;
593 }
594 node->_coordIndex.p[IndexSize++] = -1;
595 zz++;
596 }
597 zz += 2;
598 }
599}
600
601
602
603static void checkTriangleSetFields (struct X3D_TriangleSet *node) {
604 int npoints = 0;
605 int IndexSize = 0;
606 int xx; /* temporary variables */
607
608 if(node->coord) {
609 struct Multi_Vec3f *dtmp;
610 dtmp = getCoordinate (node->coord, "TriangleSet");
611 npoints = dtmp->n;
612 }
613
614 /* verify whether we have an incorrect number of coords or not */
615 if (((npoints/3)*3) != npoints) {
616 printf ("Warning, in TriangleSet, Coordinates not a multiple of 3\n");
617 npoints = ((npoints/3)*3);
618 }
619
620 /* printf ("npoints %d\n",npoints); */
621
622
623 /* calculate index size; every "face" ends in -1 */
624 IndexSize = (npoints * 4) / 3;
625 /* printf ("IndexSize is %d\n",IndexSize); */
626 node->_coordIndex.p = MALLOC (int *, sizeof(int) * IndexSize);
627 node->_coordIndex.n = IndexSize;
628
629 IndexSize = 0; /* for assigning the indexes */
630
631 /* now calculate the indexes */
632 for (xx=0; xx<npoints; xx+=3) {
633 /* printf ("index %d tris %d %d %d -1\n", xx/3, xx, xx+1, xx+2); */
634 node->_coordIndex.p[IndexSize++] = xx;
635 node->_coordIndex.p[IndexSize++] = xx+1;
636 node->_coordIndex.p[IndexSize++] = xx+2;
637 node->_coordIndex.p[IndexSize++] = -1;
638 }
639}
640
641
643void make_genericfaceset(struct X3D_IndexedFaceSet *node) {
644/* takes a variety of geometry nodes, with various subnodes for coordinates, normals, colors,
645 and for faces does delaunay triangulation with the result
646 being index[] arrays with 3 consecutive indexes per final triangle
647 (stream_polyrap will later convert the indexes into expanded coordinate arrays with
648 shared vertexes duplicated)
649*/
650 int cin;
651 int cpv = TRUE;
652 int npv;
653 int tcin;
654 int colin;
655 int norin;
656 //Aug 11, 2016 there are some complainers on web3d-public -TriangleSet too smoothed
657 // and nodes like TriangleSet don't officially have a creaseangle field like IndexedFaceSet or ElevationGrid
658 // should be if normalPerVertex = TRUE, then smooth, else no smooth and in direction according to ccw
659 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/rendering.html#TriangleSet
660 // to smooth, we set creaseAngle high -2PI keeps smoothing on- and if we detect normalPerVertex=False we put a PI/4 creaseangle
661 float creaseAngle = (float) PI * 2; // PI*2 == smooth
662 int ccw = TRUE;
663
664 int ntri = 0;
665 int nvert = 0;
666 int npoints = 0;
667 int nnormals=0;
668 int ncolors=0;
669 int vert_ind = 0;
670 int calc_normind = 0;
671
672 struct SFVec3f *c1;
673
674 struct SFVec3f *points = NULL;
675 float *fogdepths = NULL;
676 struct X3D_PolyRep *rep_ = (struct X3D_PolyRep*) node->_intern;
677
678 struct Multi_Int32 *orig_coordIndex = NULL;
679 struct Multi_Int32 *orig_texCoordIndex = NULL;
680 struct Multi_Int32 *orig_normalIndex = NULL;
681 struct Multi_Int32 *orig_colorIndex = NULL;
682
683
684 GLuint *cindex; /* Coordinate Index */
685 GLuint *colindex; /* Color Index */
686 GLuint *tcindex=0; /* Tex Coord Index */
687 GLuint *norindex; /* Normals Index */
688
689 int normalArraySize = INT_ID_UNDEFINED; /* bounds checking on normals generated */
690
691 int faces=0;
692 int convex=TRUE;
693 //struct point_XYZ *facenormals; /* normals for each face*/
694 struct SFVec3f *facenormals;
695 struct facepar *faceok = NULL; /* is this face ok? (ie, not degenerate triangles, etc)*/
696 int *pointfaces = NULL;
697
698 GLDOUBLE tess_v[3]; /*param.to FW_GLU_TESS_VERTEX()*/
699
700 int *tess_vs = NULL; /* pointer to space needed */
701
702
703 int i; /* general purpose counters */
704 int this_face, this_coord;
705
706 struct X3D_Color *cc = NULL;
707 struct X3D_Normal *nc = NULL;
708 struct X3D_TextureCoordinate *tc = NULL;
709 struct X3D_Coordinate *co = NULL;
710 struct X3D_FogCoordinate *fc = NULL;
711 ttglobal tg = gglobal();
712
713 if (node->_nodeType == NODE_IndexedFaceSet) {
714 if (!checkX3DIndexedFaceSetFields(node)) {
715 rep_->ntri = 0;
716 return;
717 }
718
719
720 } else if (node->_nodeType == NODE_ElevationGrid) {
721 if (!checkX3DElevationGridFields(X3D_ELEVATIONGRID(node),
722 (float **)&points, &npoints)) {
723 rep_->ntri = 0;
724 return;
725 }
726 } else if (node->_nodeType == NODE_GeoElevationGrid) {
727 if (!checkX3DGeoElevationGridFields(X3D_GEOELEVATIONGRID(node),
728 (float **)&points, &npoints)) {
729 rep_->ntri = 0;
730 return;
731 }
732 }
733
734 switch (node->_nodeType) {
735 case NODE_IndexedFaceSet:
736 convex = node->convex;
737 //convex = TRUE; //debugging
738 cpv = node->colorPerVertex;
739 npv = node->normalPerVertex;
740 ccw = node->ccw;
741 orig_texCoordIndex = &node->texCoordIndex;
742 orig_colorIndex = &node->colorIndex;
743 orig_normalIndex = &node->normalIndex;
744 creaseAngle = node->creaseAngle;
745 orig_coordIndex = &node->coordIndex;
746 cc = (struct X3D_Color *) node->color;
747 nc = (struct X3D_Normal *) node->normal;
748 tc = (struct X3D_TextureCoordinate *) node->texCoord;
749 co = (struct X3D_Coordinate *) node->coord;
750 fc = (struct X3D_FogCoordinate *) node->fogCoord;
751 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedFaceSet, attrib));
752 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedFaceSet, color));
753 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedFaceSet, coord));
754 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedFaceSet, fogCoord));
755 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedFaceSet, metadata));
756 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedFaceSet, normal));
757 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedFaceSet, texCoord));
758
759 break;
760 case NODE_ElevationGrid:
761 orig_coordIndex= &X3D_ELEVATIONGRID(node)->_coordIndex;
762 cpv = X3D_ELEVATIONGRID(node)->colorPerVertex;
763 npv = X3D_ELEVATIONGRID(node)->normalPerVertex;
764 creaseAngle = X3D_ELEVATIONGRID(node)->creaseAngle;
765 cc = (struct X3D_Color *) X3D_ELEVATIONGRID(node)->color;
766 nc = (struct X3D_Normal *) X3D_ELEVATIONGRID(node)->normal;
767 tc = (struct X3D_TextureCoordinate *) X3D_ELEVATIONGRID(node)->texCoord;
768 fc = (struct X3D_FogCoordinate *) X3D_ELEVATIONGRID(node)->fogCoord;
769 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_ElevationGrid, attrib));
770 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_ElevationGrid, color));
771 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_ElevationGrid, fogCoord));
772 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_ElevationGrid, metadata));
773 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_ElevationGrid, normal));
774 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_ElevationGrid, texCoord));
775 break;
776 case NODE_GeoElevationGrid:
777 orig_coordIndex= &X3D_GEOELEVATIONGRID(node)->_coordIndex;
778 cpv = X3D_GEOELEVATIONGRID(node)->colorPerVertex;
779 npv = X3D_GEOELEVATIONGRID(node)->normalPerVertex;
780 creaseAngle = (float) X3D_GEOELEVATIONGRID(node)->creaseAngle;
781 cc = (struct X3D_Color *) X3D_GEOELEVATIONGRID(node)->color;
782 nc = (struct X3D_Normal *) X3D_GEOELEVATIONGRID(node)->normal;
783 tc = (struct X3D_TextureCoordinate *) X3D_GEOELEVATIONGRID(node)->texCoord;
784 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_GeoElevationGrid, color));
785 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_GeoElevationGrid, metadata));
786 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_GeoElevationGrid, normal));
787 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_GeoElevationGrid, texCoord));
788 break;
789 case NODE_IndexedTriangleFanSet:
790 checkIndexedTriangleFanSetFields(X3D_INDEXEDTRIANGLEFANSET(node));
791 orig_coordIndex= &X3D_INDEXEDTRIANGLEFANSET(node)->_coordIndex;
792 cpv = X3D_INDEXEDTRIANGLEFANSET(node)->colorPerVertex;
793 npv = X3D_INDEXEDTRIANGLEFANSET(node)->normalPerVertex;
794 ccw = X3D_INDEXEDTRIANGLEFANSET(node)->ccw;
795 cc = (struct X3D_Color *) X3D_INDEXEDTRIANGLEFANSET(node)->color;
796 nc = (struct X3D_Normal *) X3D_INDEXEDTRIANGLEFANSET(node)->normal;
797 tc = (struct X3D_TextureCoordinate *) X3D_INDEXEDTRIANGLEFANSET(node)->texCoord;
798 co = (struct X3D_Coordinate *) X3D_INDEXEDTRIANGLEFANSET(node)->coord;
799 fc = (struct X3D_FogCoordinate *) X3D_INDEXEDTRIANGLEFANSET(node)->fogCoord;
800 if(!npv) creaseAngle = 0.0; //disable smoothing according to specs "if npv is false, don't smooth
801 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, attrib));
802 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, color));
803 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, coord));
804 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, fogCoord));
805 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, metadata));
806 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, normal));
807 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, texCoord));
808 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, index));
809 break;
810 case NODE_IndexedTriangleSet:
811 checkIndexedTriangleSetFields(X3D_INDEXEDTRIANGLESET(node));
812 orig_coordIndex= &X3D_INDEXEDTRIANGLESET(node)->_coordIndex;
813 cpv = X3D_INDEXEDTRIANGLESET(node)->colorPerVertex;
814 npv = X3D_INDEXEDTRIANGLESET(node)->normalPerVertex;
815 ccw = X3D_INDEXEDTRIANGLESET(node)->ccw;
816 cc = (struct X3D_Color *) X3D_INDEXEDTRIANGLESET(node)->color;
817 nc = (struct X3D_Normal *) X3D_INDEXEDTRIANGLESET(node)->normal;
818 tc = (struct X3D_TextureCoordinate *) X3D_INDEXEDTRIANGLESET(node)->texCoord;
819 co = (struct X3D_Coordinate *) X3D_INDEXEDTRIANGLESET(node)->coord;
820 fc = (struct X3D_FogCoordinate *) X3D_INDEXEDTRIANGLESET(node)->fogCoord;
821 if(!npv) creaseAngle = 0.0; //disable smoothing according to specs "if npv is false, don't smooth
822 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, attrib));
823 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, color));
824 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, coord));
825 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, fogCoord));
826 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, metadata));
827 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, normal));
828 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, texCoord));
829 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, index));
830 break;
831 case NODE_IndexedTriangleStripSet:
832 checkIndexedTriangleStripSetFields(X3D_INDEXEDTRIANGLESTRIPSET(node));
833 orig_coordIndex= &X3D_INDEXEDTRIANGLESTRIPSET(node)->_coordIndex;
834 cpv = X3D_INDEXEDTRIANGLESTRIPSET(node)->colorPerVertex;
835 npv = X3D_INDEXEDTRIANGLESTRIPSET(node)->normalPerVertex;
836 ccw = X3D_INDEXEDTRIANGLESTRIPSET(node)->ccw;
837 cc = (struct X3D_Color *) X3D_INDEXEDTRIANGLESTRIPSET(node)->color;
838 nc = (struct X3D_Normal *) X3D_INDEXEDTRIANGLESTRIPSET(node)->normal;
839 tc = (struct X3D_TextureCoordinate *) X3D_INDEXEDTRIANGLESTRIPSET(node)->texCoord;
840 co = (struct X3D_Coordinate *) X3D_INDEXEDTRIANGLESTRIPSET(node)->coord;
841 fc = (struct X3D_FogCoordinate *) X3D_INDEXEDTRIANGLESTRIPSET(node)->fogCoord;
842 if(!npv) creaseAngle = 0.0; //disable smoothing according to specs "if npv is false, don't smooth
843 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, attrib));
844 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, color));
845 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, coord));
846 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, fogCoord));
847 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, metadata));
848 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, normal));
849 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, texCoord));
850 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, index));
851 break;
852 case NODE_TriangleFanSet:
853 checkTriangleFanSetFields(X3D_TRIANGLEFANSET(node));
854 orig_coordIndex= &X3D_TRIANGLEFANSET(node)->_coordIndex;
855 cpv = X3D_TRIANGLEFANSET(node)->colorPerVertex;
856 npv = X3D_TRIANGLEFANSET(node)->normalPerVertex;
857 ccw = X3D_TRIANGLEFANSET(node)->ccw;
858 cc = (struct X3D_Color *) X3D_TRIANGLEFANSET(node)->color;
859 nc = (struct X3D_Normal *) X3D_TRIANGLEFANSET(node)->normal;
860 tc = (struct X3D_TextureCoordinate *) X3D_TRIANGLEFANSET(node)->texCoord;
861 co = (struct X3D_Coordinate *) X3D_TRIANGLEFANSET(node)->coord;
862 fc = (struct X3D_FogCoordinate *) X3D_TRIANGLEFANSET(node)->fogCoord;
863 if(!nc && !npv) creaseAngle = 0.0; //disable smoothing according to specs "if normals are not provided, and npv is false, don't smooth
864 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleFanSet, attrib));
865 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleFanSet, color));
866 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleFanSet, coord));
867 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleFanSet, fogCoord));
868 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleFanSet, metadata));
869 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleFanSet, normal));
870 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleFanSet, texCoord));
871 break;
872 case NODE_TriangleSet:
873 checkTriangleSetFields(X3D_TRIANGLESET(node));
874 orig_coordIndex= &X3D_TRIANGLESET(node)->_coordIndex;
875 cpv = X3D_TRIANGLESET(node)->colorPerVertex;
876 npv = X3D_TRIANGLESET(node)->normalPerVertex;
877 ccw = X3D_TRIANGLESET(node)->ccw;
878 cc = (struct X3D_Color *) X3D_TRIANGLESET(node)->color;
879 nc = (struct X3D_Normal *) X3D_TRIANGLESET(node)->normal;
880 tc = (struct X3D_TextureCoordinate *) X3D_TRIANGLESET(node)->texCoord;
881 co = (struct X3D_Coordinate *) X3D_TRIANGLESET(node)->coord;
882 fc = (struct X3D_FogCoordinate *) X3D_TRIANGLESET(node)->fogCoord;
883 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleSet, attrib));
884 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleSet, color));
885 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleSet, coord));
886 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleSet, fogCoord));
887 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleSet, metadata));
888 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleSet, normal));
889 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleSet, texCoord));
890 break;
891 case NODE_TriangleStripSet:
892 checkTriangleStripSetFields(X3D_TRIANGLESTRIPSET(node));
893 orig_coordIndex= &X3D_TRIANGLESTRIPSET(node)->_coordIndex;
894 cpv = X3D_TRIANGLESTRIPSET(node)->colorPerVertex;
895 npv = X3D_TRIANGLESTRIPSET(node)->normalPerVertex;
896 ccw = X3D_TRIANGLESTRIPSET(node)->ccw;
897 cc = (struct X3D_Color *) X3D_TRIANGLESTRIPSET(node)->color;
898 nc = (struct X3D_Normal *) X3D_TRIANGLESTRIPSET(node)->normal;
899 tc = (struct X3D_TextureCoordinate *) X3D_TRIANGLESTRIPSET(node)->texCoord;
900 co = (struct X3D_Coordinate *) X3D_TRIANGLESTRIPSET(node)->coord;
901 fc = (struct X3D_FogCoordinate *) X3D_TRIANGLESTRIPSET(node)->fogCoord;
902 if(!nc && !npv) creaseAngle = 0.0; //disable smoothing according to specs "if normals are not provided, and npv is false, don't smooth
903 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleStripSet, attrib));
904 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleStripSet, color));
905 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleStripSet, coord));
906 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleStripSet, fogCoord));
907 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleStripSet, metadata));
908 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleStripSet, normal));
909 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleStripSet, texCoord));
910 break;
911
912 case NODE_IndexedQuadSet:
913 checkIndexedQuadSetFields(X3D_INDEXEDQUADSET(node));
914 orig_coordIndex= &X3D_INDEXEDQUADSET(node)->_coordIndex;
915 cpv = X3D_INDEXEDQUADSET(node)->colorPerVertex;
916 npv = X3D_INDEXEDQUADSET(node)->normalPerVertex;
917 ccw = X3D_INDEXEDQUADSET(node)->ccw;
918 cc = (struct X3D_Color *) X3D_INDEXEDQUADSET(node)->color;
919 nc = (struct X3D_Normal *) X3D_INDEXEDQUADSET(node)->normal;
920 tc = (struct X3D_TextureCoordinate *) X3D_INDEXEDQUADSET(node)->texCoord;
921 co = (struct X3D_Coordinate *) X3D_INDEXEDQUADSET(node)->coord;
922 fc = (struct X3D_FogCoordinate *) X3D_INDEXEDQUADSET(node)->fogCoord;
923 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, attrib));
924 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, color));
925 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, coord));
926 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, fogCoord));
927 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, metadata));
928 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, normal));
929 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, texCoord));
930 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, index));
931 break;
932
933 case NODE_QuadSet:
934 checkQuadSetFields(X3D_QUADSET(node));
935 orig_coordIndex= &X3D_QUADSET(node)->_coordIndex;
936 cpv = X3D_QUADSET(node)->colorPerVertex;
937 npv = X3D_QUADSET(node)->normalPerVertex;
938 ccw = X3D_QUADSET(node)->ccw;
939 cc = (struct X3D_Color *) X3D_QUADSET(node)->color;
940 nc = (struct X3D_Normal *) X3D_QUADSET(node)->normal;
941 tc = (struct X3D_TextureCoordinate *) X3D_QUADSET(node)->texCoord;
942 co = (struct X3D_Coordinate *) X3D_QUADSET(node)->coord;
943 fc = (struct X3D_FogCoordinate *) X3D_QUADSET(node)->fogCoord;
944 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_QuadSet, attrib));
945 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_QuadSet, color));
946 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_QuadSet, coord));
947 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_QuadSet, fogCoord));
948 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_QuadSet, metadata));
949 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_QuadSet, normal));
950 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_QuadSet, texCoord));
951 break;
952
953 default:
954 ConsoleMessage ("unknown type for make_genericfaceset, %d\n",node->_nodeType);
955 rep_->ntri=0;
956 return;
957 }
958
959 if (orig_coordIndex != NULL) cin= orig_coordIndex->n; else cin = 0;
960 if (orig_texCoordIndex != NULL) tcin= orig_texCoordIndex->n; else tcin = 0;
961 if (orig_colorIndex != NULL) colin= orig_colorIndex->n; else colin = 0;
962 if (orig_normalIndex != NULL) norin= orig_normalIndex->n; else norin = 0;
963
964 #ifdef VERBOSE
965 printf ("cin %d tcin %d colin %d norin %d\n",cin,tcin,colin,norin);
966 printf ("start of make_indexedfaceset for node %p, cin %d tcin %d colin %d norin %d\n",node, cin, tcin, colin, norin);
967 #endif
968
969#undef VERBOSE
970
971
972 /* lets get the structure parameters, after munging by checkX3DComposedGeomFields... */
973 #ifdef VERBOSE
974 printf ("NOW, the IFS has a cin of %d ca %f\n",cin,creaseAngle);
975 #endif
976
977 /* check to see if there are params to make at least one triangle */
978 if (cin<2) {
979 #ifdef VERBOSE
980 printf ("Null IFS found, returing ntri0\n");
981 #endif
982 rep_->ntri = 0;
983 return;
984 }
985
986 /* record ccw flag */
987 rep_->ccw = ccw;
988
989 /* if the last coordIndex == -1, ignore it */
990 if((orig_coordIndex->p[cin-1]) == -1) { cin--; }
991
992
993 /* texture coords IndexedFaceSet coords colors and normals */
994 if(co != NULL) {
995 struct Multi_Vec3f *dtmp;
996 dtmp = getCoordinate (X3D_NODE(co), "make FacedSet");
997 npoints = dtmp->n;
998 points = dtmp->p;
999 }
1000 if(fc != NULL){
1001 //http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/enveffects.html#FogCoordinate
1002 //we have one fog per co (or if we are short, then duplicate last
1003 struct X3D_FogCoordinate *fc2;
1004 POSSIBLE_PROTO_EXPANSION (struct X3D_FogCoordinate *,(struct X3D_Node*) fc,fc2)
1005 if(fc2){
1006 if(fc2->depth.n < npoints){
1007 fc2->depth.p = REALLOC(fc2->depth.p, npoints * sizeof(float));
1008 for(i=fc2->depth.n; i<npoints; i++){
1009 fc2->depth.p[i] = fc2->depth.p[fc->depth.n-1];
1010 }
1011 fc2->depth.n = npoints;
1012 }
1013 fogdepths = fc2->depth.p;
1014 }
1015 }
1016
1017 /* just check this parameter here for correctness and, whether to generate other nodes. We
1018 will check it better in stream_polyrep. */
1019 if (cc != NULL) {
1020 if ((cc->_nodeType != NODE_Color) && (cc->_nodeType != NODE_ColorRGBA)) {
1021 printf ("make_IFS, expected %d got %d\n", NODE_Color, cc->_nodeType);
1022 } else {
1023 ncolors = cc->color.n;
1024 }
1025 }
1026
1027 if(nc != NULL) {
1028 if (nc->_nodeType != NODE_Normal) {
1029 printf ("make_IFS, normal expected %d, got %d\n",NODE_Normal, nc->_nodeType);
1030 } else {
1031 nnormals = nc->vector.n;
1032 }
1033 }
1034
1035
1036 /* just check this parameter here for correctness and, whether to generate other nodes. We
1037 will check it better in stream_polyrep. */
1038 if (tc != NULL) {
1039 rep_->tcoordtype=tc->_nodeType;
1040 } else {
1041 rep_->tcoordtype=0;
1042 }
1043
1044 /* count the faces in this polyrep and allocate memory. */
1045 faceok = MALLOC(struct facepar *, sizeof(struct facepar)*(cin/2+1));
1046 faces = count_IFS_faces (cin,orig_coordIndex,faceok);
1047 #ifdef VERBOSE
1048 printf ("faces %d, cin %d npoints %d\n",faces,cin,npoints);
1049 #endif
1050
1051 if (faces == 0) {
1052 rep_->ntri = 0;
1053 FREE_IF_NZ(faceok);
1054 return;
1055 }
1056
1057 /* are there any coordinates? */
1058 if (npoints <= 0) {
1059 rep_->ntri = 0;
1060 FREE_IF_NZ(faceok);
1061 return;
1062 }
1063
1064 //facenormals = MALLOC(struct point_XYZ *, sizeof(struct point_XYZ)*faces); // sizeof(*facenormals)
1065 facenormals = MALLOC(struct SFVec3f *, sizeof(struct SFVec3f)*faces); // sizeof(*facenormals)
1066 pointfaces = MALLOC(int *, sizeof(int)*npoints*POINT_FACES); /* save max x points */ //sizeof(*pointfaces)
1067
1068 /* generate the face-normals table, so for each face, we know the normal
1069 and for each point, we know the faces that it is in */
1070 if (!IFS_face_normals (facenormals,faceok,pointfaces,faces,npoints,cin,points,orig_coordIndex,ccw)) {
1071 rep_->ntri=0;
1072 FREE_IF_NZ (facenormals);
1073 FREE_IF_NZ (faceok);
1074 FREE_IF_NZ (pointfaces);
1075
1076 return;
1077 }
1078
1079 /* wander through to see how much memory needs allocating for triangles */
1080 /*
1081 for(i=0; i<cin; i++) {
1082 if((orig_coordIndex->p[i]) == -1) {
1083 ntri += nvert-2;
1084 nvert = 0;
1085 } else {
1086 nvert ++;
1087 }
1088 }
1089 if(nvert>2) {ntri += nvert-2;}
1090 */
1091 //https://en.wikipedia.org/wiki/Delaunay_triangulation
1092 //if there are b vertices on the convex hull, then any triangulation of the points has at most 2n - 2 - b triangles, plus one exterior face
1093 for(i=0;i<faces;i++){
1094 nvert = faceok[i].end - faceok[i].start +1;
1095 ntri += 2*nvert-2-nvert;
1096 //printf("face %d nvert %d start %d end %d\n",i,nvert,faceok[i].start,faceok[i].end);
1097 }
1098
1099
1100 //#ifdef VERBOSE
1101 //printf ("vert %d ntri %d\n",nvert,ntri);
1102 //#endif
1103
1104 /* Tesselation MAY use more triangles; lets estimate how many more */
1105 if(!convex) { ntri =ntri*2; }
1106
1107 /* fudge factor - leave space for 1 more triangle just in case we have errors on input */
1108 ntri++;
1109
1110 FREE_IF_NZ(rep_->cindex);
1111 FREE_IF_NZ(rep_->colindex);
1112 FREE_IF_NZ(rep_->norindex);
1113 FREE_IF_NZ(rep_->oindex);
1114 cindex = rep_->cindex = MALLOC(GLuint *, sizeof(*(rep_->cindex))*3*(ntri));
1115 colindex = rep_->colindex = MALLOC(GLuint *, sizeof(*(rep_->colindex))*3*(ntri));
1116 norindex = rep_->norindex = MALLOC(GLuint *,sizeof(*(rep_->norindex))*3*ntri);
1117
1118 /* zero the indexes */
1119 bzero (colindex,sizeof(*(rep_->colindex))*3*(ntri));
1120 bzero (norindex,sizeof(*(rep_->colindex))*3*(ntri));
1121
1122 FREE_IF_NZ(rep_->normal);
1123 /* if we calculate normals, we use a normal per point, NOT per triangle */
1124 if (!nnormals) { /* 3 vertexes per triangle, and 3 floats per tri */
1125 normalArraySize = 3*3*ntri;
1126 rep_->normal = MALLOC(float *, sizeof(*(rep_->normal))*normalArraySize * 2 /* JAS */ );
1127 } else { /* dont do much, but get past check below */
1128 rep_->normal = MALLOC(float *, 1);
1129 }
1130
1131 FREE_IF_NZ(rep_->tcindex);
1132
1133 tcindex = rep_->tcindex = MALLOC(GLuint*, sizeof(*(rep_->tcindex))*3*(ntri));
1134
1135 /* Concave faces - use the OpenGL Triangulator to give us the triangles */
1136 tess_vs=MALLOC(int *, sizeof(*(tess_vs))*(ntri)*3);
1137
1138 this_coord = 0;
1139 i = 0;
1140 for (this_face=0; this_face<faces; this_face++) {
1141 int relative_coord; /* temp, used if not tesselating */
1142 int tess_contour_start; /* tess, for creating contours, maybe */
1143 int initind = 0;
1144 int lastind = 0; /* coord indexes */
1145
1146 tg->Tess.global_IFS_Coord_count = 0;
1147 relative_coord = 0;
1148 tess_contour_start = 0;
1149
1150
1151 if (faceok[this_face].OK) {
1152 // #ifdef VERBOSE
1153 // printf ("in generate of faces, face %d is invalid, skipping...\n",this_face);
1154 // #endif
1155
1156 // /* skip past the seperator, except if we are t the end */
1157
1158 // /* skip to either end or the next -1*/
1159 // while ((this_coord < cin) && ((orig_coordIndex->p[this_coord]) != -1)) this_coord++;
1160
1161 // /* skip past the -1*/
1162 // if ((this_coord < (cin-1)) && ((orig_coordIndex->p[this_coord]) == -1)) this_coord++;
1163 //} else {
1164
1165 #ifdef VERBOSE
1166 printf ("working on face %d coord %d total coords %d coordIndex %d\n",
1167 this_face,this_coord,cin,(orig_coordIndex->p[ this_coord]));
1168 #endif
1169
1170 /* create the global_IFS_coords array, at least this time */
1171 /* */
1172 /* What we do is to create a series of triangle vertex */
1173 /* relative to the current coord index, then use that */
1174 /* to generate the actual coords further down. This helps */
1175 /* to map normals, textures, etc when tesselated and the */
1176 /* *perVertex modes are set. */
1177
1178 /* If we have concave, tesselate! */
1179 // July 2016 dug9 changed Tess.c combiner callback so it works for Text
1180 // but did not fix combiner scenarios here, wich were not working right when face edges intersect (which specs say don't worry about)
1181 this_coord = faceok[this_face].start;
1182
1183 if (!convex) {
1184 //register_Polyrep_combiner(); //default, Component_Text resets to this after compiling its text
1185 //FW_GLU_BEGIN_POLYGON(tg->Tess.global_tessobj);
1186 polyrep_combiner_data cbdata;
1187 //not using combinder data right now
1188 gluTessBeginPolygon( tg->Tess.global_tessobj, &cbdata); // //cbdata is for combiner
1189 gluTessBeginContour( tg->Tess.global_tessobj );
1190 } else {
1191 initind = relative_coord++;
1192 lastind = relative_coord++;
1193 }
1194
1195 i = (orig_coordIndex->p[ relative_coord + this_coord]);
1196
1197 while (i != -1) {
1198 if (!convex) {
1199 int ind;
1200 int foundContour = FALSE;
1201 /* printf ("\nwhile, i is %d this_coord %d rel coord %d\n",i,this_coord,relative_coord); */
1202
1203 /* is this a duplicate? if so, start a new contour */
1204 for (ind=tess_contour_start; ind<relative_coord; ind++) {
1205/*
1206 printf ("contour checking, comparing %d and %d, ind %d\n",
1207 orig_coordIndex->p[relative_coord + this_coord],
1208 orig_coordIndex->p[ind + this_coord],
1209 ind);
1210*/
1211 if ( orig_coordIndex->p[relative_coord + this_coord] ==
1212 orig_coordIndex->p[ind + this_coord]) {
1213 /* printf ("FOUND CONTOUR\n"); */
1214 tess_contour_start = relative_coord+1;
1215 FW_GLU_NEXT_CONTOUR(tg->Tess.global_tessobj,GLU_UNKNOWN);
1216 foundContour = TRUE;
1217 break;
1218 }
1219
1220 }
1221 if (!foundContour) {
1222 c1 = &(points[i]);
1223 tess_v[0] = c1->c[0];
1224 tess_v[1] = c1->c[1];
1225 tess_v[2] = c1->c[2];
1226 tess_vs[relative_coord] = relative_coord;
1227 /* printf ("vertex %f %f %f, index %d\n",tess_v[0], tess_v[1], tess_v[2], tess_vs[relative_coord]); */
1228 //&p->FW_RIA[p->FW_RIA_indx]
1229 //&tess_vs[relative_coord]
1230 FW_GLU_TESS_VERTEX(tg->Tess.global_tessobj,tess_v,&tess_vs[relative_coord]);
1231 }
1232
1233 relative_coord++;
1234 } else {
1235 /* take coordinates and make triangles out of them */
1236 tg->Tess.global_IFS_Coords[tg->Tess.global_IFS_Coord_count++] = initind;
1237 tg->Tess.global_IFS_Coords[tg->Tess.global_IFS_Coord_count++] = lastind;
1238 tg->Tess.global_IFS_Coords[tg->Tess.global_IFS_Coord_count++] = relative_coord;
1239 /* printf ("triangle %d %d %d\n",initind,lastind,relative_coord);*/
1240 lastind = relative_coord++;
1241 }
1242
1243 if (relative_coord + this_coord == cin) {
1244 i = -1;
1245 } else {
1246 i = (orig_coordIndex->p[ relative_coord + this_coord]);
1247 }
1248 }
1249
1250 if (!convex) {
1251 //FW_GLU_END_POLYGON(tg->Tess.global_tessobj);
1252 gluTessEndContour( tg->Tess.global_tessobj );
1253 gluTessEndPolygon( tg->Tess.global_tessobj );
1254
1255 /* Tesselated faces may have a different normal than calculated previously */
1256 /* bounds check, once again */
1257
1258 verify_global_IFS_Coords(cin);
1259
1260 // NOT SURE WHY WE WERE DOING THIS, we already have face normals I think, using
1261 // a more sophisticated method to avoid degenterate first 3 points.
1262 //IFS_check_normal (facenormals,this_face,points, this_coord, orig_coordIndex, ccw);
1263 }
1264
1265
1266 /* now store this information for the whole of the polyrep */
1267 for (i=0; i<tg->Tess.global_IFS_Coord_count; i++) {
1268 /* Triangle Coordinate */
1269 cindex [vert_ind] = (orig_coordIndex->p[this_coord+tg->Tess.global_IFS_Coords[i]]);
1270
1271 // printf ("vertex %d gic %d cindex %d\n",vert_ind, tg->Tess.global_IFS_Coords[i],cindex[vert_ind]);
1272
1273 /* Vertex Normal */
1274 if(nnormals) {
1275 int iwant,ihavei,ihaven;
1276 if (norin) {
1277 /* we have a NormalIndex */
1278 if (npv) {
1279 iwant = this_coord+tg->Tess.global_IFS_Coords[i];
1280 ihavei = min(iwant, orig_normalIndex->n-1);
1281 if(ihavei < iwant) {
1282 static int once = 0;
1283 if(!once) ConsoleMessage("not enough normal indexes have %d want %d \n",ihavei,iwant);
1284 once ++;
1285 }
1286 iwant = orig_normalIndex->p[ihavei];
1287 ihaven = min(nnormals-1,iwant);
1288 if(ihaven < iwant) {
1289 static int once = 0;
1290 if(!once) ConsoleMessage("not enough normals have %d want %d \n",ihaven,iwant);
1291 once++;
1292 }
1293 norindex[vert_ind] = ihaven;
1294 // norindex[vert_ind] = orig_normalIndex->p[this_coord+tg->Tess.global_IFS_Coords[i]];
1295 /* printf ("norm1, index %d\n",norindex[vert_ind]);*/
1296 } else {
1297 iwant = this_face;
1298 ihavei = min(iwant, orig_normalIndex->n-1);
1299 if(ihavei < iwant) {
1300 static int once = 0;
1301 if(!once) ConsoleMessage("not enough normal indexes have %d want %d \n",ihavei,iwant);
1302 once ++;
1303 }
1304 norindex[vert_ind] = ihavei; //orig_normalIndex->p[this_face];
1305 /* printf ("norm2, index %d\n",norindex[vert_ind]);*/
1306 }
1307 } else {
1308 /* no normalIndex - use the coordIndex */
1309 if (npv) {
1310 iwant = this_coord+tg->Tess.global_IFS_Coords[i];
1311 ihavei = min(iwant, norin); // min(iwant, orig_normalIndex->n - 1);
1312 if(ihavei < iwant) {
1313 static int once = 0;
1314 if(!once) ConsoleMessage("not enough normal indexes have %d want %d \n",ihavei,iwant);
1315 once ++;
1316 }
1317
1318 norindex[vert_ind] = ihavei; // (orig_coordIndex->p[this_coord+tg->Tess.global_IFS_Coords[i]]);
1319 /* printf ("norm3, index %d\n",norindex[vert_ind]); */
1320 } else {
1321 norindex[vert_ind] = this_face;
1322 /* printf ("norm4, index %d\n",norindex[vert_ind]);*/
1323 }
1324 }
1325
1326 } else {
1327 if (fabs(creaseAngle) > 0.00001) {
1328 /* normalize each vertex */
1329 if (normalArraySize != INT_ID_UNDEFINED) {
1330 if (calc_normind*3 > normalArraySize) {
1331 printf ("HMMM _ NORMAL OVERFLOW\n");
1332 }
1333 }
1334
1335 normalize_ifs_face (&rep_->normal[calc_normind*3],
1336 facenormals, pointfaces, cindex[vert_ind],
1337 this_face, creaseAngle);
1338 rep_->norindex[vert_ind] = calc_normind++;
1339 } else {
1340 /* use the calculated normals */
1341 //rep_->normal[vert_ind*3+0]=(float) facenormals[this_face].x;
1342 //rep_->normal[vert_ind*3+1]=(float) facenormals[this_face].y;
1343 //rep_->normal[vert_ind*3+2]=(float) facenormals[this_face].z;
1344 veccopy3f(&rep_->normal[vert_ind*3+0],facenormals[this_face].c);
1345 rep_->norindex[vert_ind] = vert_ind;
1346 /* printf ("using calculated normals %f %f %f for face %d, vert_ind %d\n",
1347 rep_->normal[vert_ind*3+0],rep_->normal[vert_ind*3+1],
1348 rep_->normal[vert_ind*3+2],this_face,rep_->norindex[vert_ind]);
1349 */
1350 }
1351 }
1352
1353 /* Vertex Colours */
1354 if(ncolors) {
1355 if (colin) {
1356 int tmpI;
1357 /* we have a colorIndex */
1358 if (cpv) tmpI = this_coord+tg->Tess.global_IFS_Coords[i];
1359 else tmpI = this_face;
1360
1361 if (tmpI >= orig_colorIndex->n) {
1362 printf ("faceSet, colorIndex problem, %d >= %d\n", tmpI,orig_colorIndex->n);
1363 colindex[vert_ind] = 0;
1364 } else {
1365 colindex[vert_ind] = orig_colorIndex->p[tmpI];
1366 }
1367 /* printf ("col2, index %d\n",colindex[vert_ind]); */
1368
1369 } else {
1370 /* no colorIndex - use the coordIndex */
1371 if (cpv) {
1372 colindex[vert_ind] = (orig_coordIndex->p[this_coord+tg->Tess.global_IFS_Coords[i]]);
1373 /* printf ("col3, index %d\n",colindex[vert_ind]); */
1374 } else {
1375 colindex[vert_ind] = this_face;
1376 /* printf ("col4, index %d\n",colindex[vert_ind]); */
1377 }
1378 //ConsoleMessage ("color index is %d",colindex[vert_ind]);
1379 }
1380 }
1381
1382
1383 /* Texture Coordinates */
1384 if (tcin) {
1385 /* bounds checking if we run out of texCoords, just fill in with 0 */
1386 if ((this_coord+tg->Tess.global_IFS_Coords[i]) < tcin) {
1387 tcindex[vert_ind] = orig_texCoordIndex->p[this_coord+tg->Tess.global_IFS_Coords[i]];
1388 } else {
1389 tcindex[vert_ind] = 0;
1390 }
1391 /* printf ("ntexCoords,tcin, index %d\n",tcindex[vert_ind]); */
1392 } else {
1393 /* no texCoordIndex, use the Coord Index */
1394 tcindex[vert_ind] = (orig_coordIndex->p[this_coord+tg->Tess.global_IFS_Coords[i]]);
1395 /* printf ("ntexcoords, notcin, vertex %d point %d\n",vert_ind,tcindex[vert_ind]); */
1396 }
1397 // just use cindex: fogindex[vert_ind] = (orig_coordIndex->p[this_coord+tg->Tess.global_IFS_Coords[i]]);
1398
1399 /* increment index, but check for baaad errors. */
1400 if (vert_ind < (ntri*3-1)) vert_ind++;
1401 }
1402
1403 /* for the next face, we work from a new base */
1404 this_coord += relative_coord;
1405
1406 /* skip past the seperator, except if we are t the end */
1407 if (this_coord < cin)
1408 if ((orig_coordIndex->p[this_coord]) == -1) {this_coord++;}
1409 }
1410 }
1411
1412 /* we have an accurate triangle count now... */
1413 rep_->ntri = vert_ind/3;
1414 #ifdef VERBOSE
1415 printf ("make_indededfaceset, end, ntri %d\n",rep_->ntri);
1416 #endif
1417
1418 FREE_IF_NZ (tess_vs);
1419 FREE_IF_NZ (facenormals);
1420 FREE_IF_NZ (faceok);
1421 FREE_IF_NZ (pointfaces);
1422}
1423
1424
1425
1426#undef VERBOSE
1427
1428/********************************************************************************************/
1429/* get a valid alpha angle from that that is passed in */
1430/* asin of 1.0000 seems to fail sometimes, so */
1431double getAlpha(float ang) {
1432 if (ang >= 0.99999) return asin(0.9999);
1433 else if (ang <= -0.99999) return asin(-0.9999);
1434 return asin((double)ang);
1435}
1436
1437
1438double getGamma(double alpha, double minor) {
1439 double gamma;
1440
1441 if(APPROX(cos(alpha),0))
1442 return (double) 0;
1443 else {
1444 gamma=acos(minor / cos(alpha));
1445 if(fabs(sin(gamma)-(-minor/cos(alpha)))>fabs(sin(gamma))) gamma=-gamma;
1446 }
1447 return gamma;
1448}
1449
1450void compute_spy_spz(struct point_XYZ *spy, struct point_XYZ *spz, struct SFVec3f *spine, int nspi) {
1451 int majorX = FALSE;
1452 int majorZ = FALSE;
1453 int minorY = FALSE;
1454 int minorX = FALSE;
1455 #ifdef VERBOSE
1456 int majorY = FALSE;
1457 int minorZ = FALSE;
1458 #endif
1459 double alpha,gamma; /* angles for the rotation */
1460 int spi;
1461 float spylen;
1462 struct point_XYZ spp1 = {.x=0.0, .y=0.0, .z=0.0};
1463
1464
1465 /* need to find the rotation from SCP[spi].y to (0 1 0)*/
1466 /* and rotate (0 0 1) and (0 1 0) to be the new y and z */
1467 /* values for all SCPs */
1468 /* I will choose rotation about the x and z axis */
1469
1470 /* search a non trivial vector along the spine */
1471 for(spi=1;spi<nspi;spi++) {
1472 VEC_FROM_CDIFF(spine[spi],spine[0],spp1);
1473 if(!APPROX(VECSQ(spp1),0))
1474 break;
1475 }
1476
1477 /* normalize the non trivial vector */
1478 spylen=1/(float) sqrt(VECSQ(spp1)); VECSCALE(spp1,spylen);
1479 #ifdef VERBOSE
1480 printf("Reference vector along spine=[%f,%f,%f]\n", spp1.x,spp1.y,spp1.z);
1481 #endif
1482
1483
1484 /* find the major and minor axes */
1485 if ((fabs(spp1.x) >= fabs(spp1.y)) && (fabs(spp1.x) >= fabs(spp1.z))) {majorX = TRUE;}
1486 else if ((fabs(spp1.y) >= fabs(spp1.x)) && (fabs(spp1.y) >= fabs(spp1.z))) {/* majorY = TRUE;*/ }
1487 else majorZ = TRUE;
1488 if ((fabs(spp1.x) <= fabs(spp1.y)) && (fabs(spp1.x) <= fabs(spp1.z))) {minorX = TRUE;}
1489 else if ((fabs(spp1.y) <= fabs(spp1.x)) && (fabs(spp1.y) <= fabs(spp1.z))) minorY = TRUE;
1490 else { /*minorZ = TRUE; */}
1491
1492 #ifdef VERBOSE
1493 printf ("major axis %d %d %d\n",majorX, majorY, majorZ);
1494 printf ("minor axis %d %d %d\n",minorX, minorY, minorZ);
1495 #endif
1496
1497 if(majorX) {
1498 /* get the angle for the x axis rotation */
1499 /* asin of 1.0000 seems to fail sometimes, so */
1500
1501 alpha = getAlpha((float)spp1.x);
1502 gamma = getGamma(alpha,minorY?spp1.y:spp1.z);
1503
1504 #ifdef VERBOSE
1505 printf("majorX: alpha=%f gamma=%f\n",alpha,gamma);
1506 #endif
1507
1508
1509 /* XXX: should we use the minor axis to determine the order of minor calculations???? */
1510 spy->y=-(cos(alpha)*(-sin(gamma)));
1511 spy->z=cos(alpha)*cos(gamma);
1512 spy->x=sin(alpha);
1513 spz->y=-(sin(alpha)*sin(gamma));
1514 spz->z=(-sin(alpha))*cos(gamma);
1515 spz->x=cos(alpha);
1516 } else if(majorZ) {
1517 /* get the angle for the z axis rotation */
1518
1519 alpha = getAlpha((float)spp1.z);
1520 gamma = getGamma(alpha,minorX?spp1.x:spp1.y);
1521
1522 #ifdef VERBOSE
1523 printf("majorZ: alpha=%f gamma=%f\n",alpha,gamma);
1524 #endif
1525 /* XXX: should we use the minor axis to determine the order of minor calculations???? */
1526 spy->y=-(cos(alpha)*(-sin(gamma)));
1527 spy->x=cos(alpha)*cos(gamma);
1528 spy->z=sin(alpha);
1529 spz->y=-(sin(alpha)*sin(gamma));
1530 spz->x=(-sin(alpha))*cos(gamma);
1531 spz->z=cos(alpha);
1532 } else {
1533 /* get the angle for the y axis rotation */
1534 if(1){
1535 /* dug9: Mar7,2013 special case: if spine is (all collinear +) parallel to
1536 local Y axis, just return and use defaults which are set up correctly */
1537 struct point_XYZ crossp;
1538 VECCP(*spy,spp1,crossp);
1539 if( veclengthd((double*)&crossp) < .001 ) return;
1540 }
1541 alpha = getAlpha((float)spp1.y);
1542 gamma = getGamma(alpha,minorX?spp1.x:spp1.z);
1543
1544 #ifdef VERBOSE
1545 printf("majorY: lpha=%f gamma=%f\n",alpha,gamma);
1546 #endif
1547 /* XXX: should we use the minor axis to determine the order of minor calculations???? */
1548 spy->x=-(cos(alpha)*(-sin(gamma)));
1549 spy->z=cos(alpha)*cos(gamma);
1550 spy->y=sin(alpha);
1551 spz->x=-(sin(alpha)*sin(gamma));
1552 spz->z=(-sin(alpha))*cos(gamma);
1553 spz->y=cos(alpha);
1554 }
1555}
1556
1557
1558
1559
1560
1561/***************************************************************
1562 stream the extrusion texture coords. We do this now because
1563 stream_polyrep does not go through the tcindexes - the old
1564 "render every triangle" method did. So, we gain in rendering
1565 speed for a little bit of post-processing here.
1566 ***************************************************************/
1567void stream_extrusion_texture_coords (struct X3D_PolyRep *rep_,
1568 float *tcoord,
1569 GLuint *tcindex) {
1570
1571 int count;
1572 int ind;
1573 float* nc;
1574
1575 /* printf ("stream_extrusion_texture_coords, have %d triangles \n",rep_->ntri); */
1576
1577 /* 2 floats per vertex, each triangle has 3 vertexes... */
1578 rep_->GeneratedTexCoords[0] = MALLOC (float *, sizeof(float) * 2 * 3 * rep_->ntri);
1579
1580 nc = rep_->GeneratedTexCoords[0];
1581
1582 /* go through - note now that the "span" is 2 floats per vertex, while the old
1583 method (used when the extrusion code was written) was to use 3 floats, but
1584 ignoring one of them. Thus the "ind*3" stuff below. Yes, we could go through
1585 and re-write the generator, but, who cares - the tcoord param is freed after
1586 the return of this, so the "waste" is only temporary.
1587 */
1588 for (count = 0; count < rep_->ntri*3; count++) {
1589 ind = tcindex[count];
1590 /* printf ("working through vertex %d - tcindex %d vertex %f %f \n",count,ind,
1591 tcoord[ind*3], tcoord[ind*3+2]); */
1592 *nc = tcoord[ind*3]; nc++; *nc = tcoord[ind*3+2]; nc++;
1593 }
1594}
1595
1596
1597void make_Extrusion(struct X3D_Extrusion *node) {
1598
1599 /*****begin of Member Extrusion */
1600 /* This code originates from the file VRMLExtrusion.pm */
1601
1602 int tcoordsize;
1603 int tcindexsize;
1604
1605 int beginCap = node->beginCap; /* beginCap flag */
1606 int endCap = node->endCap; /* endCap flag */
1607
1608 int nspi = node->spine.n; /* number of spine points */
1609 int nsec = node->crossSection.n; /* no. of points in the 2D curve
1610 but note that this is verified
1611 and coincident points thrown out */
1612
1613 int nori = node->orientation.n; /* no. of given orientators
1614 which rotate the calculated SCPs =
1615 spine-aligned cross-section planes*/
1616 int nsca = node->scale.n; /* no. of scale parameters */
1617
1618 struct SFVec3f *spine =node->spine.p; /* vector of spine vertices */
1619 struct SFVec2f *curve =node->crossSection.p; /* vector of 2D curve points */
1620 struct SFRotation *orientation=node->orientation.p;/*vector of SCP rotations*/
1621
1622 struct X3D_PolyRep *rep_= (struct X3D_PolyRep*) node->_intern;/*internal rep, we want to fill*/
1623
1624 /* the next variables will point at members of *rep */
1625 GLuint *cindex; /* field containing indices into
1626 the coord vector. Three together
1627 indicate which points form a
1628 triangle */
1629 float *coord; /* contains vertices building the
1630 triangles as x y z values */
1631
1632 float *tcoord; /* contains vertices building the
1633 textures as x y z values */
1634
1635 GLuint *tcindex; /* field containing texture indices
1636 for the vertex. */
1637
1638 int ntri = 0; /* no. of triangles to be used
1639 to represent all, but the caps */
1640 int nctri=0; /* no. of triangles for both caps*/
1641 int max_ncoord_add=0; /* max no. of add coords */
1642 int ncoord_add=0; /* no. off added coords */
1643 int ncoord=0; /* no. of used coords */
1644
1645 int ncolinear_at_begin=0; /* no. of triangles which need
1646 to be skipped, because curve-points
1647 are in one line at start of curve*/
1648 int ncolinear_at_end=0; /* no. of triangles which need
1649 to be skipped, because curve-points
1650 are in one line at end of curve*/
1651
1652 int spi,sec,triind,pos_of_last_zvalue; /* help variables */
1653 int next_spi, prev_spi;
1654 int t; /* another loop var */
1655
1656
1657 int circular = FALSE; /* is spine closed? */
1658 int tubular=FALSE; /* is the 2D curve closed? */
1659 int spine_is_one_vertex; /* only one real spine vertix */
1660
1661 float spxlen,spylen,spzlen; /* help vars for scaling */
1662
1663 /* def:struct representing SCPs */
1664 struct SCP { /* spine-aligned cross-section plane*/
1665 struct point_XYZ y; /* y axis of SCP */
1666 struct point_XYZ z; /* z axis of SCP */
1667 int prev,next; /* index in SCP[]
1668 prev/next different vertix for
1669 calculation of this SCP */
1670 };
1671
1672 struct SCP *SCP; /* dyn. vector rep. the SCPs */
1673
1674 struct point_XYZ spm1,spp1,spy,spz,spx; /* help vertix vars */
1675
1676 int tci_ct; /* Tex Gen index counter */
1677
1678 /* variables for calculating smooth normals */
1679 int HAVETOSMOOTH;
1680 //struct point_XYZ *facenormals = 0;
1681 struct SFVec3f *facenormals = NULL;
1682 int *pointfaces = 0;
1683 int *defaultface = 0;
1684 int this_face = 0; /* always counts up */
1685 int tmp;
1686 float creaseAngle = node->creaseAngle;
1687 int ccw = node->ccw;
1688 int end_of_sides; /* for triangle normal generation,
1689 keep track of where the sides end
1690 and caps begin */
1691
1692 /* variables for begin/endcap S,T mapping for textures */
1693 float *beginVals;
1694 float *endVals;
1695 struct SFVec2f *crossSection;
1696
1697 #ifdef VERBOSE
1698 printf ("VRMLExtrusion.pm start\n");
1699 #endif
1700
1701 /***********************************************************************
1702 *
1703 * Copy and verify cross section - remove coincident points (yes, virginia,
1704 * one of the NIST tests has this - the pie-shaped convex one
1705 *
1706 ************************************************************************/
1707/*FIXME:
1708 to prevent a crash with script generated data
1709*/
1710 if (nspi < 1) return;
1711
1712 /* is there anything to this Extrusion??? */
1713 if (nsec < 1) {
1714 rep_->ntri=0;
1715 return;
1716 } else {
1717 int tmp1, temp_indx;
1718 int increment, currentlocn;
1719
1720 crossSection = MALLOC(struct SFVec2f *, sizeof(crossSection)*nsec*2);
1721
1722
1723 currentlocn = 0;
1724 for (tmp1=0; tmp1<nsec; tmp1++) {
1725 /* save this crossSection */
1726 crossSection[currentlocn].c[0] = curve[tmp1].c[0];
1727 crossSection[currentlocn].c[1] = curve[tmp1].c[1];
1728
1729 /* assume that it is not duplicated */
1730 increment = 1;
1731 /* increment the crossSection index, unless it was duplicated */
1732 currentlocn += increment;
1733 }
1734 if(vecapprox3f(crossSection[0].c,crossSection[nsec-1].c,.001f))
1735 tubular = TRUE;
1736 #ifdef VERBOSE
1737 printf ("we had nsec %d coords, but now we have %d\n",nsec,currentlocn);
1738 #endif
1739
1740 nsec = currentlocn;
1741 }
1742
1743
1744 /* now that we have removed possible coincident vertices, we can calc ntris */
1745 ntri = 2 * (nspi-1) * (nsec-1);
1746
1747 #ifdef VERBOSE
1748 printf ("so, we have ntri %d nspi %d nsec %d\n",ntri,nspi,nsec);
1749 #endif
1750
1751 /* check if the spline is closed */
1752
1753 circular = APPROX(spine[0].c[0], spine[nspi-1].c[0]) &&
1754 APPROX(spine[0].c[1], spine[nspi-1].c[1]) &&
1755 APPROX(spine[0].c[2], spine[nspi-1].c[2]);
1756
1757 #ifdef VERBOSE
1758 printf ("tubular %d circular %d\n",tubular, circular);
1759 #endif
1760
1761
1762 /************************************************************************
1763 * calc number of triangles per cap, if caps are enabled and possible
1764 */
1765
1766 /* if we are both circular and tubular, we ignore any caps */
1767 if (circular && tubular) {
1768 beginCap = FALSE;
1769 endCap = FALSE;
1770 #ifdef VERBOSE
1771 printf ("Extrusion, turning off caps \n");
1772 #endif
1773 }
1774
1775 if(beginCap||endCap) {
1776 if(tubular?nsec<4:nsec<3) {
1777 freewrlDie("Only two real vertices in crossSection. Caps not possible!");
1778 }
1779
1780 if(tubular) nctri=nsec-2;
1781 else nctri=nsec-1;
1782
1783 #ifdef VERBOSE
1784 printf ("nsec = %d, ntri = %d nctri = %d\n",nsec, ntri,nctri);
1785 #endif
1786
1787
1788 /* check if there are colinear points at the beginning of the curve*/
1789 sec=0;
1790 while(sec+2<=nsec-1 &&
1791 /* to find out if two vectors a and b are colinear,
1792 try a.x*b.y=a.y*b.x */
1793
1794 APPROX(0, (crossSection[sec+1].c[0]-crossSection[0].c[0])
1795 *(crossSection[sec+2].c[1]-crossSection[0].c[1])
1796 - (crossSection[sec+1].c[1]-crossSection[0].c[1])
1797 *(crossSection[sec+2].c[0]-crossSection[0].c[0]))
1798 ) ncolinear_at_begin++, sec++;
1799
1800 /* check if there are colinear points at the end of the curve
1801 in line with the very first point, because we want to
1802 draw the triangle to there. */
1803 sec=tubular?(nsec-2):(nsec-1);
1804 while(sec-2>=0 &&
1805 APPROX(0, (crossSection[sec ].c[0]-crossSection[0].c[0])
1806 *(crossSection[sec-1].c[1]-crossSection[0].c[1])
1807 - (crossSection[sec ].c[1]-crossSection[0].c[1])
1808 *(crossSection[sec-1].c[0]-crossSection[0].c[0]))
1809 ) ncolinear_at_end++,sec--;
1810
1811 nctri-= ncolinear_at_begin+ncolinear_at_end;
1812
1813 if(nctri<1) {
1814 /* no triangle left :( */
1815 freewrlDie("All in crossSection points colinear. Caps not possible!");
1816 }
1817
1818 /* so we have calculated nctri for one cap, but we might have two*/
1819 nctri= ((beginCap)?nctri:0) + ((endCap)?nctri:0) ;
1820 }
1821
1822 /* if we have non-convex polygons, we might need a few triangles more */
1823 /* The unused memory will be freed with realloc later */
1824 if(!node->convex) {
1825
1826 max_ncoord_add=(nspi-1)*(nsec-1) /* because of intersections */
1827 +nctri; /* because of cap tesselation */
1828 nctri*=2; /* we might need more trigs for the caps */
1829 }
1830
1831 /************************************************************************
1832 * prepare for filling *rep
1833 */
1834
1835 rep_->ccw = 1;
1836
1837 rep_->ntri = ntri + nctri; /* Thats the no. of triangles representing
1838 the whole Extrusion Shape. */
1839
1840 /* get some memory */
1841 cindex = rep_->cindex = MALLOC(GLuint *, sizeof(*(rep_->cindex))*3*(rep_->ntri));
1842 coord = rep_->actualCoord = MALLOC(float *, sizeof(*(rep_->actualCoord))*(nspi*nsec+max_ncoord_add)*3);
1843 rep_->normal = MALLOC(float *, sizeof(*(rep_->normal))*3*(rep_->ntri)*3);
1844 rep_->norindex = MALLOC(GLuint *, sizeof(*(rep_->norindex))*3*(rep_->ntri));
1845
1846 /* face normals - one face per quad (ie, 2 triangles) */
1847 /* have to make sure that if nctri is odd, that we increment by one */
1848
1849
1850 //facenormals = MALLOC(struct point_XYZ *, sizeof(*facenormals)*(rep_->ntri+1)/2);
1851 facenormals = MALLOC(struct SFVec3f *, sizeof(struct SFVec3f)*(rep_->ntri+1)/2);
1852
1853 /* for each triangle vertex, tell me which face(s) it is in */
1854 pointfaces = MALLOC(int *, sizeof(*pointfaces)*POINT_FACES*3*rep_->ntri);
1855
1856 /* for each triangle, it has a defaultface... */
1857 defaultface = MALLOC(int *, sizeof(*defaultface)*rep_->ntri);
1858
1859
1860 /*memory for the SCPs. Only needed in this function. Freed later */
1861 SCP = MALLOC(struct SCP *, sizeof(struct SCP)*nspi);
1862
1863 /* so, we now have to worry about textures. */
1864 /* XXX note - this over-estimates; realloc to be exact */
1865
1866 tcoordsize = (nctri + (ntri*2))*3;
1867
1868 #ifdef VERBOSE
1869 printf ("tcoordsize is %d\n",tcoordsize);
1870 # endif
1871
1872 FREE_IF_NZ (rep_->GeneratedTexCoords[0]);
1873 FREE_IF_NZ (rep_->tcindex);
1874
1875 tcoord = MALLOC(float *, sizeof(*(rep_->GeneratedTexCoords[0]))*tcoordsize);
1876
1877 tcindexsize = rep_->ntri*3;
1878 #ifdef VERBOSE
1879 printf ("tcindexsize %d\n",tcindexsize);
1880 #endif
1881
1882 tcindex = MALLOC(GLuint *, sizeof(*(rep_->tcindex))*tcindexsize);
1883
1884 /* keep around cross section info for tex coord mapping */
1885 beginVals = MALLOC(float *, sizeof(float) * 2 * (nsec+1)*100);
1886 endVals = MALLOC(float *, sizeof(float) * 2 * (nsec+1)*100);
1887
1888 memset((void *)tcindex,0,tcindexsize*sizeof(*(rep_->tcindex)));
1889 /* printf ("zeroing tcindex\n");*/
1890 /* { int i; for (i=0; i<tcindexsize; i++) { tcindex[i]=0; } }*/
1891
1892 /* Normal Generation Code */
1893 HAVETOSMOOTH = (fabs(creaseAngle)>0.0001);
1894 for (tmp = 0; tmp < 3*rep_->ntri; tmp++) {
1895 pointfaces[tmp*POINT_FACES]=0;
1896 }
1897
1898
1899 /************************************************************************
1900 * calculate all SCPs
1901 */
1902
1903 spine_is_one_vertex=0;
1904
1905 /* fill the prev and next values in the SCP structs first
1906 *
1907 * this is so complicated, because spine vertices can be the same
1908 * They should have exactly the same SCP, therefore only one of
1909 * an group of sucessive equal spine vertices (now called SESVs)
1910 * must be used for calculation.
1911 * For calculation the previous and next different spine vertex
1912 * must be known. We save that info in the prev and next fields of
1913 * the SCP struct.
1914 * Note: We have start and end SESVs which will be treated differently
1915 * depending on whether the spine is closed or not
1916 *
1917 */
1918
1919 for(spi=0; spi<nspi;spi++){
1920 for(next_spi=spi+1;next_spi<nspi;next_spi++) {
1921 VEC_FROM_CDIFF(spine[spi],spine[next_spi],spp1);
1922 if(!APPROX(VECSQ(spp1),0))
1923 break;
1924 }
1925 if(next_spi<nspi) SCP[next_spi].prev=next_spi-1;
1926
1927 #ifdef VERBOSE
1928 printf("spi=%d next_spi=%d\n",spi,next_spi); /**/
1929 #endif
1930
1931 prev_spi=spi-1;
1932 SCP[spi].next=next_spi;
1933 SCP[spi].prev=prev_spi;
1934
1935 while(next_spi>spi+1) { /* fill gaps */
1936 spi++;
1937 SCP[spi].next=next_spi;
1938 SCP[spi].prev=prev_spi;
1939 }
1940 }
1941 /* now: start-SEVS .prev fields contain -1 */
1942 /* and end-SEVS .next fields contain nspi */
1943
1944
1945 /* calculate the SCPs now... */
1946
1947 #ifdef VERBOSE
1948 printf (" SCP[0].next = %d, nspi = %d\n",SCP[0].next,nspi);
1949 #endif
1950
1951
1952
1953 if(SCP[0].next==nspi) {
1954 spine_is_one_vertex=1;
1955 #ifdef VERBOSE
1956 printf("All spine vertices are the same!\n");
1957 #endif
1958
1959 /* initialize all y and z values with zero, they will */
1960 /* be treated as colinear case later then */
1961 SCP[0].z.x=0; SCP[0].z.y=0; SCP[0].z.z=0;
1962 SCP[0].y=SCP[0].z;
1963 for(spi=1;spi<nspi;spi++) {
1964 SCP[spi].y=SCP[0].y;
1965 SCP[spi].z=SCP[0].z;
1966 }
1967 }else{
1968 #ifdef VERBOSE
1969 for(spi=0;spi<nspi;spi++) {
1970 printf("SCP[%d].next=%d, SCP[%d].prev=%d\n",
1971 spi,SCP[spi].next,spi,SCP[spi].prev);
1972 }
1973 #endif
1974
1975 /* find spine vertix different to the first spine vertix */
1976 spi=0;
1977 while(SCP[spi].prev==-1) spi++;
1978
1979 /* find last spine vertix different to the last */
1980 t=nspi-1;
1981 while(SCP[t].next==nspi) t--;
1982
1983 #ifdef VERBOSE
1984 printf ("now, spi = %d, t = %d\n",spi,t);
1985 #endif
1986
1987 /* for all but the first + last really different spine vertix */
1988 /* add case for then there are only 2 spines, and spi is already */
1989 /* spi is already greater than t... JAS */
1990
1991 if (spi > t) {
1992 /* calc y */
1993 VEC_FROM_CDIFF(spine[1],spine[0],SCP[0].y);
1994 /* calc z */
1995 VEC_FROM_CDIFF(spine[1],spine[0],spp1);
1996 if(0){
1997 VEC_FROM_CDIFF(spine[1],spine[0],spm1);
1998 VECCP(spp1,spm1,SCP[1].z);
1999 }
2000 if(1){
2001 //dug9 Mar7,2013 from specs
2002 // http://www.web3d.org/files/specifications/19775-1/V3.2/Part01/components/geometry3D.html#Extrusion
2003 //in 13.3.5.4 Special Cases "
2004 //If the entire spine is collinear, the SCP is computed by finding
2005 //the rotation of a vector along the positive Y-axis (v1) to the vector
2006 //formed by the spine points (v2). The Y=0 plane is then rotated by this value.
2007 struct point_XYZ Yaxis; //scene local Y axis (up)
2008 double dlen_cp;
2009 Yaxis.x = 0.0;
2010 Yaxis.y = 1.0;
2011 Yaxis.z = 0.0;
2012 VECCP(spp1,Yaxis,SCP[1].z);
2013 //but what if the Yaxis is aligned pretty much to the spine axis?
2014 //then the cross product will be zero. We want a unit vector. So use Zaxis.
2015 dlen_cp = veclengthd((double*)&(SCP[1].z));
2016 if( dlen_cp < .001 )
2017 {
2018 SCP[1].z.x = 0.0;
2019 SCP[1].z.y = 0.0;
2020 SCP[1].z.z = 1.0; //align z to local scene Z axis, like flux, cortona, white_dune, blaxxun, cosmo
2021 }
2022 }
2023 #ifdef VERBOSE
2024 printf ("just calculated z for spi 0\n");
2025 printf("SCP[0].y=[%f,%f,%f], SCP[1].z=[%f,%f,%f]\n",
2026 SCP[0].y.x,SCP[0].y.y,SCP[0].y.z,
2027 SCP[1].z.x,SCP[1].z.y,SCP[1].z.z);
2028 #endif
2029 }
2030
2031 else {
2032 for(; spi<=t; spi++) {
2033 /* calc y */
2034 VEC_FROM_CDIFF(spine[SCP[spi].next],spine[SCP[spi].prev],SCP[spi].y);
2035 /* calc z */
2036 VEC_FROM_CDIFF(spine[SCP[spi].next],spine[spi],spp1);
2037 VEC_FROM_CDIFF(spine[SCP[spi].prev],spine[spi],spm1);
2038 VECCP(spp1,spm1,SCP[spi].z);
2039 #ifdef VERBOSE
2040 printf ("just calculated z for spi %d\n",spi);
2041 #endif
2042 }
2043 }
2044
2045 if(circular) {
2046 #ifdef VERBOSE
2047 printf ("we are circular\n");
2048 #endif
2049 /* calc y for first SCP */
2050 VEC_FROM_CDIFF(spine[SCP[0].next],spine[SCP[nspi-1].prev],SCP[0].y);
2051 /* the last is the same as the first */
2052 SCP[nspi-1].y=SCP[0].y;
2053
2054 /* calc z */
2055 VEC_FROM_CDIFF(spine[SCP[0].next],spine[0],spp1);
2056 VEC_FROM_CDIFF(spine[SCP[nspi-1].prev],spine[0],spm1);
2057 VECCP(spp1,spm1,SCP[0].z);
2058 /* the last is the same as the first */
2059 SCP[nspi-1].z=SCP[0].z;
2060
2061 } else {
2062 #ifdef VERBOSE
2063 printf ("we are not circular\n");
2064 #endif
2065
2066 /* calc y for first SCP */
2067 VEC_FROM_CDIFF(spine[SCP[0].next],spine[0],SCP[0].y);
2068
2069 /* calc y for the last SCP */
2070 /* in the case of 2, nspi-1 = 1, ...prev = 0 */
2071 VEC_FROM_CDIFF(spine[nspi-1],spine[SCP[nspi-1].prev],SCP[nspi-1].y);
2072
2073 /* z for the start SESVs is the same as for the next SCP */
2074 SCP[0].z=SCP[SCP[0].next].z;
2075 /* z for the last SCP is the same as for the one before the last*/
2076 SCP[nspi-1].z=SCP[SCP[nspi-1].prev].z;
2077
2078 #ifdef VERBOSE
2079 printf("SCP[0].y=[%f,%f,%f], SCP[0].z=[%f,%f,%f]\n",
2080 SCP[0].y.x,SCP[0].y.y,SCP[0].y.z,
2081 SCP[0].z.x,SCP[0].z.y,SCP[0].z.z);
2082 printf("SCP[1].y=[%f,%f,%f], SCP[1].z=[%f,%f,%f]\n",
2083 SCP[1].y.x,SCP[1].y.y,SCP[1].y.z,
2084 SCP[1].z.x,SCP[1].z.y,SCP[1].z.z);
2085 #endif
2086 } /* else */
2087
2088 /* fill the other start SESVs SCPs*/
2089 spi=1;
2090 while(SCP[spi].prev==-1) {
2091 SCP[spi].y=SCP[0].y;
2092 SCP[spi].z=SCP[0].z;
2093 spi++;
2094 }
2095 /* fill the other end SESVs SCPs*/
2096 t=nspi-2;
2097 while(SCP[t].next==nspi) {
2098 SCP[t].y=SCP[nspi-1].y;
2099 SCP[t].z=SCP[nspi-1].z;
2100 t--;
2101 }
2102
2103 } /* else */
2104
2105
2106 /* We have to deal with colinear cases, what means z=0 */
2107 pos_of_last_zvalue=-1; /* where a zvalue is found */
2108 for(spi=0;spi<nspi;spi++) {
2109 if(pos_of_last_zvalue>=0) { /* already found one? */
2110 if(APPROX(VECSQ(SCP[spi].z),0))
2111 SCP[spi].z= SCP[pos_of_last_zvalue].z;
2112
2113 pos_of_last_zvalue=spi;
2114 } else
2115 if(!APPROX(VECSQ(SCP[spi].z),0)) {
2116 /* we got the first, fill the previous */
2117 #ifdef VERBOSE
2118 printf("Found z-Value!\n");
2119 #endif
2120
2121 for(t=spi-1; t>-1; t--)
2122 SCP[t].z=SCP[spi].z;
2123 pos_of_last_zvalue=spi;
2124 }
2125 }
2126
2127 #ifdef VERBOSE
2128 printf("pos_of_last_zvalue=%d\n",pos_of_last_zvalue);
2129 #endif
2130
2131
2132 /* z axis flipping, if VECPT(SCP[i].z,SCP[i-1].z)<0 */
2133 /* we can do it here, because it is not needed in the all-colinear case */
2134 for(spi=(circular?2:1);spi<nspi;spi++) {
2135 if(VECPT(SCP[spi].z,SCP[spi-1].z)<0) {
2136 VECSCALE(SCP[spi].z,-1);
2137 #ifdef VERBOSE
2138 printf("Extrusion.GenPloyRep: Flipped axis spi=%d\n",spi);
2139 #endif
2140 }
2141 } /* for */
2142
2143 /* One case is missing: whole spine is colinear */
2144 if(pos_of_last_zvalue==-1) {
2145
2146 #ifdef VERBOSE
2147 printf("Extrusion.GenPloyRep:Whole spine is colinear!\n");
2148 #endif
2149
2150 /* this is the default, if we don`t need to rotate */
2151 spy.x=0; spy.y=1; spy.z=0;
2152 spz.x=0; spz.y=0; spz.z=1;
2153
2154 if(!spine_is_one_vertex) {
2155 compute_spy_spz(&spy,&spz,spine,nspi);
2156 }
2157
2158 #ifdef VERBOSE
2159 printf ("so, spy [%f %f %f], spz [%f %f %f]\n", spy.x, spy.y,spy.z, spz.x, spz.y, spz.z);
2160 #endif
2161
2162 /* apply new y and z values to all SCPs */
2163 for(spi=0;spi<nspi;spi++) {
2164 SCP[spi].y=spy;
2165 SCP[spi].z=spz;
2166 }
2167
2168 } /* if all colinear */
2169
2170 #ifdef VERBOSE
2171 for(spi=0;spi<nspi;spi++) {
2172 printf("SCP[%d].y=[%f,%f,%f], SCP[%d].z=[%f,%f,%f]\n",
2173 spi,SCP[spi].y.x,SCP[spi].y.y,SCP[spi].y.z,
2174 spi,SCP[spi].z.x,SCP[spi].z.y,SCP[spi].z.z);
2175 }
2176 #endif
2177
2178
2179 /************************************************************************
2180 * calculate the coords
2181 */
2182
2183 /* test for number of scale and orientation parameters */
2184 if(nsca>1 && nsca <nspi)
2185 printf("Extrusion.GenPolyRep: Warning!\n"
2186 "\tNumber of scaling parameters do not match the number of spines!\n"
2187 "\tWill revert to using only the first scale value.\n");
2188
2189 if(nori>1 && nori <nspi)
2190 printf("Extrusion.GenPolyRep: Warning!\n"
2191 "\tNumber of orientation parameters "
2192 "do not match the number of spines!\n"
2193 "\tWill revert to using only the first orientation value.\n");
2194
2195
2196 for(spi = 0; spi<nspi; spi++) {
2197 double m[3][3]; /* space for the rotation matrix */
2198 spy=SCP[spi].y;
2199 spz=SCP[spi].z;
2200 VECCP(spy,spz,spx);
2201 spylen = 1/(float)sqrt(VECSQ(spy)); VECSCALE(spy, spylen);
2202 spzlen = 1/(float)sqrt(VECSQ(spz)); VECSCALE(spz, spzlen);
2203 spxlen = 1/(float)sqrt(VECSQ(spx)); VECSCALE(spx, spxlen);
2204
2205 /* rotate spx spy and spz */
2206 if(nori) {
2207 int ori = (nori==nspi ? spi : 0);
2208
2209 if(IS_ROTATION_VEC_NOT_NORMAL(orientation[ori]))
2210 printf("Extrusion.GenPolyRep: Warning!\n"
2211 "\tRotationvector #%d not normal!\n"
2212 "\tWon`t correct it, because it is bad VRML`97.\n",
2213 ori+1);
2214
2215 MATRIX_FROM_ROTATION(orientation[ori],m);
2216 VECMM(m,spx);
2217 VECMM(m,spy);
2218 VECMM(m,spz);
2219 }
2220
2221 for(sec = 0; sec<nsec; sec++) {
2222 struct point_XYZ point;
2223 float ptx = crossSection[sec].c[0];
2224 float ptz = crossSection[sec].c[1];
2225 if(nsca) {
2226 int sca = (nsca==nspi ? spi : 0);
2227 ptx *= node->scale.p[sca].c[0];
2228 ptz *= node->scale.p[sca].c[1];
2229 }
2230 point.x = ptx;
2231 point.y = 0;
2232 point.z = ptz;
2233
2234 /* printf ("working on sec %d of %d, spine %d of %d\n", sec, nsec, spi, nspi);*/
2235
2236
2237 /* texture mapping for caps - keep vals around */
2238 if (spi == 0) { /* begin cap vertices */
2239 /* printf ("begin cap vertecies index %d %d \n", sec*2+0, sec*2+1); */
2240
2241 beginVals[sec*2+0] = ptx;
2242 beginVals[sec*2+1] = ptz;
2243 } else if (spi == (nspi-1)) { /* end cap vertices */
2244 /* printf ("end cap vertecies index %d %d size %d\n", sec*2+0, sec*2+1, 2 * (nsec+1));*/
2245 endVals[(sec*2)+0]=ptx;
2246 endVals[(sec*2)+1]=ptz;
2247 }
2248
2249 /* printf ("coord index %x sec %d spi %d nsec %d\n",*/
2250 /* &coord[(sec+spi*nsec)*3+0], sec, spi,nsec);*/
2251
2252 coord[(sec+spi*nsec)*3+0] =
2253 (float)(spx.x * point.x + spy.x * point.y + spz.x * point.z)
2254 + node->spine.p[spi].c[0];
2255 coord[(sec+spi*nsec)*3+1] =
2256 (float)(spx.y * point.x + spy.y * point.y + spz.y * point.z)
2257 + node->spine.p[spi].c[1];
2258 coord[(sec+spi*nsec)*3+2] =
2259 (float)(spx.z * point.x + spy.z * point.y + spz.z * point.z)
2260 + node->spine.p[spi].c[2];
2261
2262 } /* for(sec */
2263 } /* for(spi */
2264 ncoord=nsec*nspi;
2265
2266
2267 /* freeing SCP coordinates. not needed anymore. */
2268 FREE_IF_NZ (SCP);
2269
2270 /************************************************************************
2271 * setting the values of *cindex to the right coords
2272 */
2273
2274 triind = 0;
2275 {
2276 int x,z;
2277 int A,B,C,D; /* should referr to the four vertices of the polygon
2278 (hopefully) counted counter-clockwise, like
2279
2280 D----C
2281 | |
2282 | |
2283 | |
2284 A----B
2285
2286 */
2287 int Atex, Btex, Ctex, Dtex, Etex, Ftex; /* Tex Coord points */
2288
2289 struct point_XYZ ac,bd, /* help vectors */
2290 ab,cd; /* help vectors for testing intersection */
2291 int E,F; /* third point to be used for the triangles*/
2292 double u,r, /* help variables for testing intersection */
2293 denominator, /* ... */
2294 numerator; /* ... */
2295
2296 #ifdef VERBOSE
2297 printf("Coords: \n");
2298
2299 for(x=0; x<nsec; x++) {
2300 for(z=0; z<nspi; z++) {
2301 int xxx = 3*(x+z*nsec);
2302 printf("coord: %d [%f %f %f] ",(x+z*nsec),
2303 coord[xxx], coord[xxx+1], coord[xxx+2]);
2304
2305 }
2306 printf("\n");
2307 }
2308 printf("\n");
2309 #endif
2310
2311
2312 /* Now, lay out the spines/sections, and generate triangles */
2313 //register_Polyrep_combiner(); //default, component_text resets to this after compiling its text
2314 for(x=0; x<nsec-1; x++) {
2315 for(z=0; z<nspi-1; z++) {
2316 A=x+z*nsec;
2317 B=(x+1)+z*nsec;
2318 C=(x+1)+(z+1)*nsec;
2319 D= x+(z+1)*nsec;
2320
2321 /* texture mapping coords */
2322 Atex = A; Btex = B; Ctex = C; Dtex = D;
2323
2324 /* if we are circular, check to see if this is the first tri, or the last */
2325 /* the vertexes are identical, but for smooth normal calcs, make the */
2326 /* indexes the same, too */
2327 /* note, we dont touch tex coords here. */
2328 /* printf ("x %d z %d nsec %d nspi %d\n",x,z,nsec,nspi);*/
2329
2330 if (tubular) {
2331 /* printf ("tubular, x %d nsec %d this_face %d\n",x,nsec,this_face);*/
2332 if (x==(nsec-2)) {
2333 B -=(x+1);
2334 C -=(x+1);
2335 }
2336 }
2337
2338 if (circular) {
2339 if (z==(nspi-2)) {
2340 /* last row in column, assume z=nspi-2, subtract this off */
2341 C -= (z+1)*nsec;
2342 D -= (z+1)*nsec;
2343 }
2344 }
2345
2346 /* calculate the distance A-C and see, if it is smaller as B-D */
2347 VEC_FROM_COORDDIFF(coord,C,coord,A,ac);
2348 VEC_FROM_COORDDIFF(coord,D,coord,B,bd);
2349
2350 if(sqrt(VECSQ(ac))>sqrt(VECSQ(bd))) {
2351 E=B; F=D; Etex=Btex; Ftex=Dtex;
2352 } else {
2353 E=C; F=A; Etex=Ctex; Ftex=Atex;
2354 }
2355
2356 /* if concave polygons are expected, we also expect intersecting ones
2357 so we are testing, whether A-B and D-C intersect */
2358 if(!node->convex) {
2359 VEC_FROM_COORDDIFF(coord,B,coord,A,ab);
2360 VEC_FROM_COORDDIFF(coord,D,coord,C,cd);
2361 /* ca=-ac */
2362 #ifdef VERBOSE
2363 printf("ab=[%f,%f,%f],cd=[%f,%f,%f]\n",
2364 ab.x,ab.y,ab.z,cd.x,cd.y,cd.z);
2365 printf("Orig: %d %d [%f %f %f] [%f %f %f] (%d, %d, %d) \n",
2366 D, C,
2367 coord[D*3], coord[D*3+1], coord[D*3+2],
2368 coord[C*3], coord[C*3+1], coord[C*3+2],
2369 ncoord, nsec, nspi
2370 );
2371 #endif
2372
2373 denominator= ab.y*cd.x-ab.x*cd.y;
2374 numerator = (-ac.x)*cd.y-(-ac.y)*cd.x;
2375
2376 r=u=-1;
2377 if(!APPROX(denominator,0)) {
2378 u=numerator/denominator;
2379 r=((-ac.x)*ab.y-(-ac.y)*ab.x)/denominator;
2380 } else {
2381 /* lines still may be coincident*/
2382 if(APPROX(numerator,0)) {
2383 /* we have to calculate u and r using the z coord*/
2384 denominator=ab.z*cd.x-ab.x*cd.z;
2385 numerator = (-ac.x)*cd.z-(-ac.z)*cd.x;
2386 if(!APPROX(denominator,0)) {
2387 u=numerator/denominator;
2388 r=((-ac.x)*ab.y-(-ac.y)*ab.x)/denominator;
2389 }
2390 }
2391 } /* else */
2392 #ifdef VERBOSE
2393 printf("u=%f, r=%f\n",u,r);
2394 #endif
2395
2396 if(u>=0 && u<=1 && r>=0 && r<=1
2397 && APPROX((-ac.x)+u*ab.x,r*cd.x)
2398 && APPROX((-ac.y)+u*ab.y,r*cd.y)
2399 && APPROX((-ac.z)+u*ab.z,r*cd.z)) {
2400
2401 #ifdef VERBOSE
2402 printf("Intersection found at P=[%f,%f,%f]!\n",
2403 coord[A*3]+u*ab.x,
2404 coord[A*3+1]+u*ab.y,
2405 coord[A*3+2]+u*ab.y
2406 );
2407 #endif
2408
2409 coord[(ncoord)*3 ]=coord[A*3 ]+(float)(u*ab.x);
2410 coord[(ncoord)*3+1]=coord[A*3+1]+(float)(u*ab.y);
2411 coord[(ncoord)*3+2]=coord[A*3+2]+(float)(u*ab.z);
2412 E=ncoord;
2413 F=ncoord;
2414 ncoord_add++;
2415 ncoord++;
2416 }
2417
2418 }
2419
2420 /* printf ("tcindex %d\n",tcindex);*/
2421 /* printf ("Triangle1 %d %d %d\n",D,A,E);*/
2422 /* first triangle calculate pointfaces, etc, for this face */
2423 Elev_Tri(triind*3, this_face, D,A,E, TRUE , rep_, facenormals, pointfaces,ccw);
2424
2425 tcindex[triind*3] = (GLuint)Dtex;
2426 tcindex[triind*3+2] = (GLuint)Etex;
2427 tcindex[triind*3+1] = (GLuint)Atex;
2428
2429 defaultface[triind] = this_face;
2430 triind++;
2431
2432 /* printf ("Triangle2 %d %d %d\n",B,C,F);*/
2433 /* second triangle - pointfaces, etc,for this face */
2434 Elev_Tri(triind*3, this_face, B, C, F, TRUE, rep_, facenormals, pointfaces,ccw);
2435
2436 tcindex[triind*3] = (GLuint)Btex;
2437 tcindex[triind*3+1] = (GLuint)Ctex;
2438 tcindex[triind*3+2] = (GLuint)Ftex;
2439
2440 if ((triind*3+2) >= tcindexsize)
2441 printf ("INTERNAL ERROR: Extrusion - tcindex size too small!\n");
2442 defaultface[triind] = this_face;
2443 triind ++;
2444 this_face ++;
2445
2446 }
2447 }
2448
2449 /* do normal calculations for the sides, here */
2450 for (tmp=0; tmp<(triind*3); tmp++) {
2451 if (HAVETOSMOOTH) {
2452 normalize_ifs_face (&rep_->normal[tmp*3],
2453 facenormals, pointfaces, cindex[tmp],
2454 defaultface[tmp/3], creaseAngle);
2455 } else {
2456 int iiface = defaultface[tmp/3];
2457 veccopy3f(&rep_->normal[tmp*3+0],facenormals[iiface].c);
2458 //rep_->normal[tmp*3+0] = (float) facenormals[defaultface[tmp/3]].x;
2459 //rep_->normal[tmp*3+1] = (float) facenormals[defaultface[tmp/3]].y;
2460 //rep_->normal[tmp*3+2] = (float) facenormals[defaultface[tmp/3]].z;
2461 }
2462 rep_->norindex[tmp] = (GLuint)tmp;
2463 }
2464 /* keep track of where the sides end, triangle count-wise, for Normal mapping */
2465 end_of_sides = triind*3;
2466
2467 /* tcindexes are TOTALLY different from sides - set this in case we are
2468 doing textures in the end caps */
2469 tci_ct = nspi*nsec;
2470
2471 if(node->convex) {
2472 int endpoint;
2473
2474 int triind_start; /* textures need 2 passes */
2475
2476 /* if not tubular, we need one more triangle */
2477 if (tubular) endpoint = nsec-3-ncolinear_at_end;
2478 else endpoint = nsec-2-ncolinear_at_end;
2479
2480
2481 /* printf ("beginCap, starting at triind %d\n",triind);*/
2482
2483 /* this is the simple case with convex polygons */
2484 if(beginCap) {
2485 triind_start = triind;
2486
2487 for(x=0+ncolinear_at_begin; x<endpoint; x++) {
2488 Elev_Tri(triind*3, this_face, 0, x+2, x+1, TRUE , rep_, facenormals, pointfaces,ccw);
2489 defaultface[triind] = this_face;
2490 Extru_tex(triind*3, tci_ct, 0 , +x+2, x+1, tcindex ,ccw,tcindexsize);
2491 triind ++;
2492 }
2493
2494 Extru_ST_map(triind_start,0+ncolinear_at_begin,endpoint,
2495 beginVals,nsec,tcindex, cindex, tcoord, tcoordsize);
2496 tci_ct+=endpoint-(0+ncolinear_at_begin);
2497 triind_start+=endpoint-(0+ncolinear_at_begin);
2498 this_face++;
2499 } /* if beginCap */
2500
2501 if(endCap) {
2502 triind_start = triind;
2503
2504 for(x=0+ncolinear_at_begin; x<endpoint; x++) {
2505 Elev_Tri(triind*3, this_face, 0 +(nspi-1)*nsec,
2506 x+1+(nspi-1)*nsec,x+2+(nspi-1)*nsec,
2507 TRUE , rep_, facenormals, pointfaces,ccw);
2508 defaultface[triind] = this_face;
2509 Extru_tex(triind*3, tci_ct, 0+(nspi-1)*nsec,
2510 x+1+(nspi-1)*nsec,
2511 x+2+(nspi-1)*nsec,
2512 tcindex,ccw,tcindexsize);
2513 triind ++;
2514 }
2515 this_face++;
2516 Extru_ST_map(triind_start,0+ncolinear_at_begin,endpoint,
2517 endVals, nsec, tcindex, cindex, tcoord, tcoordsize);
2518 } /* if endCap */
2519 /* for (tmp=0;tmp<tcindexsize; tmp++) printf ("index1D %d tcindex %d\n",tmp,tcindex[tmp]);*/
2520
2521 } else
2522 if(beginCap || endCap) {
2523 /* polygons might be concave-> do tessellation */
2524 /* XXX - no textures yet - Linux Tesselators give me enough headaches;
2525 lets wait until they are all ok before trying texture mapping */
2526
2527 /* give us some memory - this array will contain tessd triangle counts */
2528 int *tess_vs;
2529 struct SFVec3f *c1;
2530 GLDOUBLE tess_v[3];
2531 int endpoint;
2532 ttglobal tg = gglobal();
2533 int max_combiner = 30;
2534 tess_vs=MALLOC(int *, sizeof(*(tess_vs)) * (nsec - 3 - ncolinear_at_end + max_combiner) * 3);
2535 int last_vertex = 2*nsec + (nspi-1)*nsec;
2536 /* if not tubular, we need one more triangle */
2537 if (tubular) endpoint = nsec-1-ncolinear_at_end;
2538 else endpoint = nsec-ncolinear_at_end;
2539 polyrep_combiner_data cbdata;
2540 set_tess_callbacks(1);
2541 cbdata.coords = rep_->actualCoord; // p->FW_rep_->actualCoord;
2542 cbdata.counter = &last_vertex; //&tg->Tess.global_IFS_Coord_count;
2543 cbdata.ria = tess_vs;
2544 cbdata.riaindex = &x;
2545
2546 if (beginCap) {
2547 tg->Tess.global_IFS_Coord_count = 0;
2548 gluTessNormal(tg->Tess.text_tessobj,0.0,1.0,0.0);
2549
2550 //FW_GLU_BEGIN_POLYGON(tg->Tess.global_tessobj);
2551 gluTessBeginPolygon( tg->Tess.global_tessobj, &cbdata );
2552 gluTessBeginContour( tg->Tess.global_tessobj );
2553
2554 for(x=0+ncolinear_at_begin; x<endpoint; x++) {
2555 /* printf ("starting tv for x %d of %d\n",x,endpoint);*/
2556 c1 = (struct SFVec3f *) &rep_->actualCoord[3*x];
2557 /* printf ("and, coords for this one are: %f %f %f\n",*/
2558 /* c1->c[0], c1->c[1],c1->c[2]);*/
2559
2560 tess_v[0] = c1->c[0]; tess_v[1] = c1->c[1]; tess_v[2] = c1->c[2];
2561 tess_vs[x] = x;
2562 FW_GLU_TESS_VERTEX(tg->Tess.global_tessobj,tess_v,&tess_vs[x]);
2563 }
2564 //FW_GLU_END_POLYGON(tg->Tess.global_tessobj);
2565 gluTessEndContour( tg->Tess.global_tessobj );
2566 gluTessEndPolygon( tg->Tess.global_tessobj );
2567
2568 verify_global_IFS_Coords(ntri*3);
2569
2570 for (x=0; x<tg->Tess.global_IFS_Coord_count; x+=3) {
2571 /* printf ("now, in 2nd for loop, x %d glob %d\n",x,*/
2572 /* global_IFS_Coord_count);*/
2573 Elev_Tri(triind*3, this_face, tg->Tess.global_IFS_Coords[x],
2574 tg->Tess.global_IFS_Coords[x+2], tg->Tess.global_IFS_Coords[x+1],
2575 TRUE , rep_, facenormals, pointfaces,ccw);
2576 defaultface[triind] = this_face;
2577 triind ++;
2578 }
2579 /* Tesselated faces may have a different normal than calculated previously */
2580 Extru_check_normal (facenormals,this_face,-1,rep_,ccw);
2581
2582 this_face++;
2583 }
2584
2585 if (endCap) {
2586 tg->Tess.global_IFS_Coord_count = 0;
2587 //FW_GLU_BEGIN_POLYGON(tg->Tess.global_tessobj);
2588 gluTessNormal(tg->Tess.text_tessobj,0.0,1.0,0.0);
2589
2590 gluTessBeginPolygon( tg->Tess.global_tessobj, &cbdata );
2591 gluTessBeginContour( tg->Tess.global_tessobj );
2592
2593 for(x=0+ncolinear_at_begin; x<endpoint; x++) {
2594 c1 = (struct SFVec3f *) &rep_->actualCoord[3*(x+(nspi-1)*nsec)];
2595 tess_v[0] = c1->c[0]; tess_v[1] = c1->c[1]; tess_v[2] = c1->c[2];
2596 tess_vs[x] = x+(nspi-1)*nsec;
2597 FW_GLU_TESS_VERTEX(tg->Tess.global_tessobj,tess_v,&tess_vs[x]);
2598 }
2599 //FW_GLU_END_POLYGON(tg->Tess.global_tessobj);
2600 gluTessEndContour( tg->Tess.global_tessobj );
2601 gluTessEndPolygon( tg->Tess.global_tessobj );
2602
2603 verify_global_IFS_Coords(ntri*3);
2604
2605 for (x=0; x<tg->Tess.global_IFS_Coord_count; x+=3) {
2606 Elev_Tri(triind*3, this_face, tg->Tess.global_IFS_Coords[x],
2607 tg->Tess.global_IFS_Coords[x+1], tg->Tess.global_IFS_Coords[x+2],
2608 TRUE , rep_, facenormals, pointfaces,ccw);
2609 defaultface[triind] = this_face;
2610 triind ++;
2611 }
2612 /* Tesselated faces may have a different normal than calculated previously */
2613 Extru_check_normal (facenormals,this_face,1,rep_,ccw);
2614
2615 this_face++;
2616 }
2617 //tg->Tess.last_slot = NULL;
2618 set_tess_callbacks(0);
2619
2620 /* get rid of MALLOCd memory for tess */
2621 FREE_IF_NZ (tess_vs);
2622 } /* elseif */
2623
2624 } /* end of block */
2625
2626 /* if we have tesselated, we MAY have fewer triangles than estimated, so... */
2627 rep_->ntri=triind;
2628
2629 /* for (tmp=0;tmp<tcindexsize; tmp++) printf ("index2 %d tcindex %d\n",tmp,tcindex[tmp]);*/
2630 /* do normal calculations for the caps here note - no smoothing */
2631 for (tmp=end_of_sides; tmp<(triind*3); tmp++) {
2632 int iiface = defaultface[tmp/3];
2633 veccopy3f(&rep_->normal[tmp*3+0],facenormals[iiface].c);
2634 //rep_->normal[tmp*3+0] = (float) facenormals[defaultface[tmp/3]].x;
2635 //rep_->normal[tmp*3+1] = (float) facenormals[defaultface[tmp/3]].y;
2636 //rep_->normal[tmp*3+2] = (float) facenormals[defaultface[tmp/3]].z;
2637 rep_->norindex[tmp] = (GLuint)tmp;
2638 }
2639
2640 /* do texture mapping calculations for sides */
2641 /* range check - this should NEVER happen... */
2642 if (tcoordsize <= ((nsec-1)+(nspi-1)*(nsec-1)*3+2)) {
2643 printf ("INTERNAL ERROR: Extrusion side tcoord calcs nspi %d nsec %d tcoordsize %d\n",
2644 nspi,nsec,tcoordsize);
2645 }
2646 for(sec=0; sec<nsec; sec++) {
2647 for(spi=0; spi<nspi; spi++) {
2648 /* printf ("tcoord idx %d %d %d tcoordsize %d ",*/
2649 /* (sec+spi*nsec)*3,(sec+spi*nsec)*3+1,(sec+spi*nsec)*3+2,tcoordsize);*/
2650 /* printf ("side texts sec %d spi %d\n",sec,spi);*/
2651 tcoord[(sec+spi*nsec)*3+0] = (float) sec/(nsec-1);
2652 tcoord[(sec+spi*nsec)*3+1] = 0;
2653 tcoord[(sec+spi*nsec)*3+2] = (float) spi/(nspi-1);
2654 /* printf (" %f %f\n",tcoord[(sec+spi*nsec)*3+0],tcoord[(sec+spi*nsec)*3+2]);*/
2655 }
2656 }
2657
2658 #ifdef VERBOSE
2659 printf ("done, lets free\n");
2660 #endif
2661
2662 /* we no longer need to keep normal-generating memory around */
2663 FREE_IF_NZ (defaultface);
2664 FREE_IF_NZ (pointfaces);
2665 FREE_IF_NZ (facenormals);
2666 FREE_IF_NZ (crossSection);
2667
2668 FREE_IF_NZ (beginVals);
2669 FREE_IF_NZ (endVals);
2670
2671
2672 /* stream the texture coords so that they are linear as tcindex is not used in stream_polyrep */
2673 stream_extrusion_texture_coords (rep_, tcoord, tcindex);
2674
2675 /* now that the tex coords are streamed, remove the temoporary arrays */
2676 FREE_IF_NZ (tcoord);
2677 FREE_IF_NZ (tcindex);
2678
2679
2680 #ifdef VERBOSE
2681 printf("Extrusion.GenPloyRep: triind=%d ntri=%d nctri=%d "
2682 "ncolinear_at_begin=%d ncolinear_at_end=%d\n",
2683 triind,ntri,nctri,ncolinear_at_begin,ncolinear_at_end);
2684
2685 printf ("end VRMLExtrusion.pm\n");
2686 #endif
2687
2688 /*****end of Member Extrusion */
2689}