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 = 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
642
643void make_genericfaceset(struct X3D_IndexedFaceSet *node) {
644 int cin;
645 int cpv = TRUE;
646 int npv;
647 int tcin;
648 int colin;
649 int norin;
650 //Aug 11, 2016 there are some complainers on web3d-public -TriangleSet too smoothed
651 // and nodes like TriangleSet don't officially have a creaseangle field like IndexedFaceSet or ElevationGrid
652 // should be if normalPerVertex = TRUE, then smooth, else no smooth and in direction according to ccw
653 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/rendering.html#TriangleSet
654 // to smooth, we set creaseAngle high -2PI keeps smoothing on- and if we detect normalPerVertex=False we put a PI/4 creaseangle
655 float creaseAngle = (float) PI * 2; // PI*2 == smooth
656 int ccw = TRUE;
657
658 int ntri = 0;
659 int nvert = 0;
660 int npoints = 0;
661 int nnormals=0;
662 int ncolors=0;
663 int vert_ind = 0;
664 int calc_normind = 0;
665
666 struct SFVec3f *c1;
667
668 struct SFVec3f *points = NULL;
669 float *fogdepths = NULL;
670 struct X3D_PolyRep *rep_ = node->_intern;
671
672 struct Multi_Int32 *orig_coordIndex = NULL;
673 struct Multi_Int32 *orig_texCoordIndex = NULL;
674 struct Multi_Int32 *orig_normalIndex = NULL;
675 struct Multi_Int32 *orig_colorIndex = NULL;
676
677
678 GLuint *cindex; /* Coordinate Index */
679 GLuint *colindex; /* Color Index */
680 GLuint *tcindex=0; /* Tex Coord Index */
681 GLuint *norindex; /* Normals Index */
682
683 int normalArraySize = INT_ID_UNDEFINED; /* bounds checking on normals generated */
684
685 int faces=0;
686 int convex=TRUE;
687 //struct point_XYZ *facenormals; /* normals for each face*/
688 struct SFVec3f *facenormals;
689 int *faceok = NULL; /* is this face ok? (ie, not degenerate triangles, etc)*/
690 int *pointfaces = NULL;
691
692 GLDOUBLE tess_v[3]; /*param.to FW_GLU_TESS_VERTEX()*/
693
694 int *tess_vs = NULL; /* pointer to space needed */
695
696
697 int i; /* general purpose counters */
698 int this_face, this_coord;
699
700 struct X3D_Color *cc = NULL;
701 struct X3D_Normal *nc = NULL;
702 struct X3D_TextureCoordinate *tc = NULL;
703 struct X3D_Coordinate *co = NULL;
704 struct X3D_FogCoordinate *fc = NULL;
705 ttglobal tg = gglobal();
706
707 if (node->_nodeType == NODE_IndexedFaceSet) {
708 if (!checkX3DIndexedFaceSetFields(node)) {
709 rep_->ntri = 0;
710 return;
711 }
712
713
714 } else if (node->_nodeType == NODE_ElevationGrid) {
715 if (!checkX3DElevationGridFields(X3D_ELEVATIONGRID(node),
716 (float **)&points, &npoints)) {
717 rep_->ntri = 0;
718 return;
719 }
720 } else if (node->_nodeType == NODE_GeoElevationGrid) {
721 if (!checkX3DGeoElevationGridFields(X3D_GEOELEVATIONGRID(node),
722 (float **)&points, &npoints)) {
723 rep_->ntri = 0;
724 return;
725 }
726 }
727
728 switch (node->_nodeType) {
729 case NODE_IndexedFaceSet:
730 convex = node->convex;
731 //convex = TRUE; //debugging
732 cpv = node->colorPerVertex;
733 npv = node->normalPerVertex;
734 ccw = node->ccw;
735 orig_texCoordIndex = &node->texCoordIndex;
736 orig_colorIndex = &node->colorIndex;
737 orig_normalIndex = &node->normalIndex;
738 creaseAngle = node->creaseAngle;
739 orig_coordIndex = &node->coordIndex;
740 cc = (struct X3D_Color *) node->color;
741 nc = (struct X3D_Normal *) node->normal;
742 tc = (struct X3D_TextureCoordinate *) node->texCoord;
743 co = (struct X3D_Coordinate *) node->coord;
744 fc = (struct X3D_FogCoordinate *) node->fogCoord;
745 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedFaceSet, attrib));
746 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedFaceSet, color));
747 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedFaceSet, coord));
748 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedFaceSet, fogCoord));
749 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedFaceSet, metadata));
750 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedFaceSet, normal));
751 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedFaceSet, texCoord));
752
753 break;
754 case NODE_ElevationGrid:
755 orig_coordIndex= &X3D_ELEVATIONGRID(node)->_coordIndex;
756 cpv = X3D_ELEVATIONGRID(node)->colorPerVertex;
757 npv = X3D_ELEVATIONGRID(node)->normalPerVertex;
758 creaseAngle = X3D_ELEVATIONGRID(node)->creaseAngle;
759 cc = (struct X3D_Color *) X3D_ELEVATIONGRID(node)->color;
760 nc = (struct X3D_Normal *) X3D_ELEVATIONGRID(node)->normal;
761 tc = (struct X3D_TextureCoordinate *) X3D_ELEVATIONGRID(node)->texCoord;
762 fc = (struct X3D_FogCoordinate *) X3D_ELEVATIONGRID(node)->fogCoord;
763 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_ElevationGrid, attrib));
764 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_ElevationGrid, color));
765 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_ElevationGrid, fogCoord));
766 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_ElevationGrid, metadata));
767 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_ElevationGrid, normal));
768 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_ElevationGrid, texCoord));
769 break;
770 case NODE_GeoElevationGrid:
771 orig_coordIndex= &X3D_GEOELEVATIONGRID(node)->_coordIndex;
772 cpv = X3D_GEOELEVATIONGRID(node)->colorPerVertex;
773 npv = X3D_GEOELEVATIONGRID(node)->normalPerVertex;
774 creaseAngle = (float) X3D_GEOELEVATIONGRID(node)->creaseAngle;
775 cc = (struct X3D_Color *) X3D_GEOELEVATIONGRID(node)->color;
776 nc = (struct X3D_Normal *) X3D_GEOELEVATIONGRID(node)->normal;
777 tc = (struct X3D_TextureCoordinate *) X3D_GEOELEVATIONGRID(node)->texCoord;
778 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_GeoElevationGrid, color));
779 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_GeoElevationGrid, metadata));
780 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_GeoElevationGrid, normal));
781 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_GeoElevationGrid, texCoord));
782 break;
783 case NODE_IndexedTriangleFanSet:
784 checkIndexedTriangleFanSetFields(X3D_INDEXEDTRIANGLEFANSET(node));
785 orig_coordIndex= &X3D_INDEXEDTRIANGLEFANSET(node)->_coordIndex;
786 cpv = X3D_INDEXEDTRIANGLEFANSET(node)->colorPerVertex;
787 npv = X3D_INDEXEDTRIANGLEFANSET(node)->normalPerVertex;
788 ccw = X3D_INDEXEDTRIANGLEFANSET(node)->ccw;
789 cc = (struct X3D_Color *) X3D_INDEXEDTRIANGLEFANSET(node)->color;
790 nc = (struct X3D_Normal *) X3D_INDEXEDTRIANGLEFANSET(node)->normal;
791 tc = (struct X3D_TextureCoordinate *) X3D_INDEXEDTRIANGLEFANSET(node)->texCoord;
792 co = (struct X3D_Coordinate *) X3D_INDEXEDTRIANGLEFANSET(node)->coord;
793 fc = (struct X3D_FogCoordinate *) X3D_INDEXEDTRIANGLEFANSET(node)->fogCoord;
794 if(!npv) creaseAngle = 0.0; //disable smoothing according to specs "if npv is false, don't smooth
795 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, attrib));
796 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, color));
797 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, coord));
798 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, fogCoord));
799 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, metadata));
800 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, normal));
801 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, texCoord));
802 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, index));
803 break;
804 case NODE_IndexedTriangleSet:
805 checkIndexedTriangleSetFields(X3D_INDEXEDTRIANGLESET(node));
806 orig_coordIndex= &X3D_INDEXEDTRIANGLESET(node)->_coordIndex;
807 cpv = X3D_INDEXEDTRIANGLESET(node)->colorPerVertex;
808 npv = X3D_INDEXEDTRIANGLESET(node)->normalPerVertex;
809 ccw = X3D_INDEXEDTRIANGLESET(node)->ccw;
810 cc = (struct X3D_Color *) X3D_INDEXEDTRIANGLESET(node)->color;
811 nc = (struct X3D_Normal *) X3D_INDEXEDTRIANGLESET(node)->normal;
812 tc = (struct X3D_TextureCoordinate *) X3D_INDEXEDTRIANGLESET(node)->texCoord;
813 co = (struct X3D_Coordinate *) X3D_INDEXEDTRIANGLESET(node)->coord;
814 fc = (struct X3D_FogCoordinate *) X3D_INDEXEDTRIANGLESET(node)->fogCoord;
815 if(!npv) creaseAngle = 0.0; //disable smoothing according to specs "if npv is false, don't smooth
816 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, attrib));
817 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, color));
818 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, coord));
819 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, fogCoord));
820 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, metadata));
821 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, normal));
822 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, texCoord));
823 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleSet, index));
824 break;
825 case NODE_IndexedTriangleStripSet:
826 checkIndexedTriangleStripSetFields(X3D_INDEXEDTRIANGLESTRIPSET(node));
827 orig_coordIndex= &X3D_INDEXEDTRIANGLESTRIPSET(node)->_coordIndex;
828 cpv = X3D_INDEXEDTRIANGLESTRIPSET(node)->colorPerVertex;
829 npv = X3D_INDEXEDTRIANGLESTRIPSET(node)->normalPerVertex;
830 ccw = X3D_INDEXEDTRIANGLESTRIPSET(node)->ccw;
831 cc = (struct X3D_Color *) X3D_INDEXEDTRIANGLESTRIPSET(node)->color;
832 nc = (struct X3D_Normal *) X3D_INDEXEDTRIANGLESTRIPSET(node)->normal;
833 tc = (struct X3D_TextureCoordinate *) X3D_INDEXEDTRIANGLESTRIPSET(node)->texCoord;
834 co = (struct X3D_Coordinate *) X3D_INDEXEDTRIANGLESTRIPSET(node)->coord;
835 fc = (struct X3D_FogCoordinate *) X3D_INDEXEDTRIANGLESTRIPSET(node)->fogCoord;
836 if(!npv) creaseAngle = 0.0; //disable smoothing according to specs "if npv is false, don't smooth
837 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, attrib));
838 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, color));
839 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, coord));
840 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, fogCoord));
841 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, metadata));
842 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, normal));
843 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, texCoord));
844 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedTriangleStripSet, index));
845 break;
846 case NODE_TriangleFanSet:
847 checkTriangleFanSetFields(X3D_TRIANGLEFANSET(node));
848 orig_coordIndex= &X3D_TRIANGLEFANSET(node)->_coordIndex;
849 cpv = X3D_TRIANGLEFANSET(node)->colorPerVertex;
850 npv = X3D_TRIANGLEFANSET(node)->normalPerVertex;
851 ccw = X3D_TRIANGLEFANSET(node)->ccw;
852 cc = (struct X3D_Color *) X3D_TRIANGLEFANSET(node)->color;
853 nc = (struct X3D_Normal *) X3D_TRIANGLEFANSET(node)->normal;
854 tc = (struct X3D_TextureCoordinate *) X3D_TRIANGLEFANSET(node)->texCoord;
855 co = (struct X3D_Coordinate *) X3D_TRIANGLEFANSET(node)->coord;
856 fc = (struct X3D_FogCoordinate *) X3D_TRIANGLEFANSET(node)->fogCoord;
857 if(!nc && !npv) creaseAngle = 0.0; //disable smoothing according to specs "if normals are not provided, and npv is false, don't smooth
858 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleFanSet, attrib));
859 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleFanSet, color));
860 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleFanSet, coord));
861 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleFanSet, fogCoord));
862 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleFanSet, metadata));
863 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleFanSet, normal));
864 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleFanSet, texCoord));
865 break;
866 case NODE_TriangleSet:
867 checkTriangleSetFields(X3D_TRIANGLESET(node));
868 orig_coordIndex= &X3D_TRIANGLESET(node)->_coordIndex;
869 cpv = X3D_TRIANGLESET(node)->colorPerVertex;
870 npv = X3D_TRIANGLESET(node)->normalPerVertex;
871 ccw = X3D_TRIANGLESET(node)->ccw;
872 cc = (struct X3D_Color *) X3D_TRIANGLESET(node)->color;
873 nc = (struct X3D_Normal *) X3D_TRIANGLESET(node)->normal;
874 tc = (struct X3D_TextureCoordinate *) X3D_TRIANGLESET(node)->texCoord;
875 co = (struct X3D_Coordinate *) X3D_TRIANGLESET(node)->coord;
876 fc = (struct X3D_FogCoordinate *) X3D_TRIANGLESET(node)->fogCoord;
877 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleSet, attrib));
878 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleSet, color));
879 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleSet, coord));
880 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleSet, fogCoord));
881 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleSet, metadata));
882 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleSet, normal));
883 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleSet, texCoord));
884 break;
885 case NODE_TriangleStripSet:
886 checkTriangleStripSetFields(X3D_TRIANGLESTRIPSET(node));
887 orig_coordIndex= &X3D_TRIANGLESTRIPSET(node)->_coordIndex;
888 cpv = X3D_TRIANGLESTRIPSET(node)->colorPerVertex;
889 npv = X3D_TRIANGLESTRIPSET(node)->normalPerVertex;
890 ccw = X3D_TRIANGLESTRIPSET(node)->ccw;
891 cc = (struct X3D_Color *) X3D_TRIANGLESTRIPSET(node)->color;
892 nc = (struct X3D_Normal *) X3D_TRIANGLESTRIPSET(node)->normal;
893 tc = (struct X3D_TextureCoordinate *) X3D_TRIANGLESTRIPSET(node)->texCoord;
894 co = (struct X3D_Coordinate *) X3D_TRIANGLESTRIPSET(node)->coord;
895 fc = (struct X3D_FogCoordinate *) X3D_TRIANGLESTRIPSET(node)->fogCoord;
896 if(!nc && !npv) creaseAngle = 0.0; //disable smoothing according to specs "if normals are not provided, and npv is false, don't smooth
897 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleStripSet, attrib));
898 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleStripSet, color));
899 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleStripSet, coord));
900 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleStripSet, fogCoord));
901 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleStripSet, metadata));
902 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleStripSet, normal));
903 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_TriangleStripSet, texCoord));
904 break;
905
906 case NODE_IndexedQuadSet:
907 checkIndexedQuadSetFields(X3D_INDEXEDQUADSET(node));
908 orig_coordIndex= &X3D_INDEXEDQUADSET(node)->_coordIndex;
909 cpv = X3D_INDEXEDQUADSET(node)->colorPerVertex;
910 npv = X3D_INDEXEDQUADSET(node)->normalPerVertex;
911 ccw = X3D_INDEXEDQUADSET(node)->ccw;
912 cc = (struct X3D_Color *) X3D_INDEXEDQUADSET(node)->color;
913 nc = (struct X3D_Normal *) X3D_INDEXEDQUADSET(node)->normal;
914 tc = (struct X3D_TextureCoordinate *) X3D_INDEXEDQUADSET(node)->texCoord;
915 co = (struct X3D_Coordinate *) X3D_INDEXEDQUADSET(node)->coord;
916 fc = (struct X3D_FogCoordinate *) X3D_INDEXEDQUADSET(node)->fogCoord;
917 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, attrib));
918 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, color));
919 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, coord));
920 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, fogCoord));
921 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, metadata));
922 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, normal));
923 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, texCoord));
924 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_IndexedQuadSet, index));
925 break;
926
927 case NODE_QuadSet:
928 checkQuadSetFields(X3D_QUADSET(node));
929 orig_coordIndex= &X3D_QUADSET(node)->_coordIndex;
930 cpv = X3D_QUADSET(node)->colorPerVertex;
931 npv = X3D_QUADSET(node)->normalPerVertex;
932 ccw = X3D_QUADSET(node)->ccw;
933 cc = (struct X3D_Color *) X3D_QUADSET(node)->color;
934 nc = (struct X3D_Normal *) X3D_QUADSET(node)->normal;
935 tc = (struct X3D_TextureCoordinate *) X3D_QUADSET(node)->texCoord;
936 co = (struct X3D_Coordinate *) X3D_QUADSET(node)->coord;
937 fc = (struct X3D_FogCoordinate *) X3D_QUADSET(node)->fogCoord;
938 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_QuadSet, attrib));
939 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_QuadSet, color));
940 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_QuadSet, coord));
941 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_QuadSet, fogCoord));
942 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_QuadSet, metadata));
943 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_QuadSet, normal));
944 MARK_EVENT (X3D_NODE(node), offsetof (struct X3D_QuadSet, texCoord));
945 break;
946
947 default:
948 ConsoleMessage ("unknown type for make_genericfaceset, %d\n",node->_nodeType);
949 rep_->ntri=0;
950 return;
951 }
952
953 if (orig_coordIndex != NULL) cin= orig_coordIndex->n; else cin = 0;
954 if (orig_texCoordIndex != NULL) tcin= orig_texCoordIndex->n; else tcin = 0;
955 if (orig_colorIndex != NULL) colin= orig_colorIndex->n; else colin = 0;
956 if (orig_normalIndex != NULL) norin= orig_normalIndex->n; else norin = 0;
957
958 #ifdef VERBOSE
959 printf ("cin %d tcin %d colin %d norin %d\n",cin,tcin,colin,norin);
960 printf ("start of make_indexedfaceset for node %p, cin %d tcin %d colin %d norin %d\n",node, cin, tcin, colin, norin);
961 #endif
962
963#undef VERBOSE
964
965
966 /* lets get the structure parameters, after munging by checkX3DComposedGeomFields... */
967 #ifdef VERBOSE
968 printf ("NOW, the IFS has a cin of %d ca %f\n",cin,creaseAngle);
969 #endif
970
971 /* check to see if there are params to make at least one triangle */
972 if (cin<2) {
973 #ifdef VERBOSE
974 printf ("Null IFS found, returing ntri0\n");
975 #endif
976 rep_->ntri = 0;
977 return;
978 }
979
980 /* record ccw flag */
981 rep_->ccw = ccw;
982
983 /* if the last coordIndex == -1, ignore it */
984 if((orig_coordIndex->p[cin-1]) == -1) { cin--; }
985
986
987 /* texture coords IndexedFaceSet coords colors and normals */
988 if(co != NULL) {
989 struct Multi_Vec3f *dtmp;
990 dtmp = getCoordinate (X3D_NODE(co), "make FacedSet");
991 npoints = dtmp->n;
992 points = dtmp->p;
993 }
994 if(fc != NULL){
995 //http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/enveffects.html#FogCoordinate
996 //we have one fog per co (or if we are short, then duplicate last
997 struct X3D_FogCoordinate *fc2;
998 POSSIBLE_PROTO_EXPANSION (struct X3D_FogCoordinate *,(struct X3D_Node*) fc,fc2)
999 if(fc2){
1000 if(fc2->depth.n < npoints){
1001 fc2->depth.p = REALLOC(fc2->depth.p, npoints * sizeof(float));
1002 for(i=fc2->depth.n; i<npoints; i++){
1003 fc2->depth.p[i] = fc2->depth.p[fc->depth.n-1];
1004 }
1005 fc2->depth.n = npoints;
1006 }
1007 fogdepths = fc2->depth.p;
1008 }
1009 }
1010
1011 /* just check this parameter here for correctness and, whether to generate other nodes. We
1012 will check it better in stream_polyrep. */
1013 if (cc != NULL) {
1014 if ((cc->_nodeType != NODE_Color) && (cc->_nodeType != NODE_ColorRGBA)) {
1015 printf ("make_IFS, expected %d got %d\n", NODE_Color, cc->_nodeType);
1016 } else {
1017 ncolors = cc->color.n;
1018 }
1019 }
1020
1021 if(nc != NULL) {
1022 if (nc->_nodeType != NODE_Normal) {
1023 printf ("make_IFS, normal expected %d, got %d\n",NODE_Normal, nc->_nodeType);
1024 } else {
1025 nnormals = nc->vector.n;
1026 }
1027 }
1028
1029
1030 /* just check this parameter here for correctness and, whether to generate other nodes. We
1031 will check it better in stream_polyrep. */
1032 if (tc != NULL) {
1033 rep_->tcoordtype=tc->_nodeType;
1034 } else {
1035 rep_->tcoordtype=0;
1036 }
1037
1038 /* count the faces in this polyrep and allocate memory. */
1039 faces = count_IFS_faces (cin,orig_coordIndex);
1040 #ifdef VERBOSE
1041 printf ("faces %d, cin %d npoints %d\n",faces,cin,npoints);
1042 #endif
1043
1044 if (faces == 0) {
1045 rep_->ntri = 0;
1046 return;
1047 }
1048
1049 /* are there any coordinates? */
1050 if (npoints <= 0) {
1051 rep_->ntri = 0;
1052 return;
1053 }
1054
1055 //facenormals = MALLOC(struct point_XYZ *, sizeof(struct point_XYZ)*faces); // sizeof(*facenormals)
1056 facenormals = MALLOC(struct SFVec3f *, sizeof(struct SFVec3f)*faces); // sizeof(*facenormals)
1057 faceok = MALLOC(int *, sizeof(int)*faces);
1058 pointfaces = MALLOC(int *, sizeof(int)*npoints*POINT_FACES); /* save max x points */ //sizeof(*pointfaces)
1059
1060 /* generate the face-normals table, so for each face, we know the normal
1061 and for each point, we know the faces that it is in */
1062 if (!IFS_face_normals (facenormals,faceok,pointfaces,faces,npoints,cin,points,orig_coordIndex,ccw)) {
1063 rep_->ntri=0;
1064 FREE_IF_NZ (facenormals);
1065 FREE_IF_NZ (faceok);
1066 FREE_IF_NZ (pointfaces);
1067
1068 return;
1069 }
1070
1071 /* wander through to see how much memory needs allocating for triangles */
1072 for(i=0; i<cin; i++) {
1073 if((orig_coordIndex->p[i]) == -1) {
1074 ntri += nvert-2;
1075 nvert = 0;
1076 } else {
1077 nvert ++;
1078 }
1079 }
1080 if(nvert>2) {ntri += nvert-2;}
1081
1082
1083 #ifdef VERBOSE
1084 printf ("vert %d ntri %d\n",nvert,ntri);
1085 #endif
1086
1087 /* Tesselation MAY use more triangles; lets estimate how many more */
1088 if(!convex) { ntri =ntri*2; }
1089
1090 /* fudge factor - leave space for 1 more triangle just in case we have errors on input */
1091 ntri++;
1092
1093 FREE_IF_NZ(rep_->cindex);
1094 FREE_IF_NZ(rep_->colindex);
1095 FREE_IF_NZ(rep_->norindex);
1096
1097 cindex = rep_->cindex = MALLOC(GLuint *, sizeof(*(rep_->cindex))*3*(ntri));
1098 colindex = rep_->colindex = MALLOC(GLuint *, sizeof(*(rep_->colindex))*3*(ntri));
1099 norindex = rep_->norindex = MALLOC(GLuint *,sizeof(*(rep_->norindex))*3*ntri);
1100
1101 /* zero the indexes */
1102 bzero (colindex,sizeof(*(rep_->colindex))*3*(ntri));
1103 bzero (norindex,sizeof(*(rep_->colindex))*3*(ntri));
1104
1105 FREE_IF_NZ(rep_->normal);
1106 /* if we calculate normals, we use a normal per point, NOT per triangle */
1107 if (!nnormals) { /* 3 vertexes per triangle, and 3 floats per tri */
1108 normalArraySize = 3*3*ntri;
1109 rep_->normal = MALLOC(float *, sizeof(*(rep_->normal))*normalArraySize * 2 /* JAS */ );
1110 } else { /* dont do much, but get past check below */
1111 rep_->normal = MALLOC(float *, 1);
1112 }
1113
1114 FREE_IF_NZ(rep_->tcindex);
1115
1116 tcindex = rep_->tcindex = MALLOC(GLuint*, sizeof(*(rep_->tcindex))*3*(ntri));
1117
1118 /* Concave faces - use the OpenGL Triangulator to give us the triangles */
1119 tess_vs=MALLOC(int *, sizeof(*(tess_vs))*(ntri)*3);
1120
1121 this_coord = 0;
1122 i = 0;
1123 for (this_face=0; this_face<faces; this_face++) {
1124 int relative_coord; /* temp, used if not tesselating */
1125 int tess_contour_start; /* tess, for creating contours, maybe */
1126 int initind = 0;
1127 int lastind = 0; /* coord indexes */
1128
1129 tg->Tess.global_IFS_Coord_count = 0;
1130 relative_coord = 0;
1131 tess_contour_start = 0;
1132
1133
1134 if (!faceok[this_face]) {
1135 #ifdef VERBOSE
1136 printf ("in generate of faces, face %d is invalid, skipping...\n",this_face);
1137 #endif
1138
1139 /* skip past the seperator, except if we are t the end */
1140
1141 /* skip to either end or the next -1*/
1142 while ((this_coord < cin) && ((orig_coordIndex->p[this_coord]) != -1)) this_coord++;
1143
1144 /* skip past the -1*/
1145 if ((this_coord < (cin-1)) && ((orig_coordIndex->p[this_coord]) == -1)) this_coord++;
1146 } else {
1147
1148 #ifdef VERBOSE
1149 printf ("working on face %d coord %d total coords %d coordIndex %d\n",
1150 this_face,this_coord,cin,(orig_coordIndex->p[ this_coord]));
1151 #endif
1152
1153 /* create the global_IFS_coords array, at least this time */
1154 /* */
1155 /* What we do is to create a series of triangle vertex */
1156 /* relative to the current coord index, then use that */
1157 /* to generate the actual coords further down. This helps */
1158 /* to map normals, textures, etc when tesselated and the */
1159 /* *perVertex modes are set. */
1160
1161 /* If we have concave, tesselate! */
1162 // July 2016 dug9 changed Tess.c combiner callback so it works for Text
1163 // but did not fix combiner scenarios here, wich were not working right when face edges intersect (which specs say don't worry about)
1164 if (!convex) {
1165 //register_Polyrep_combiner(); //default, Component_Text resets to this after compiling its text
1166 //FW_GLU_BEGIN_POLYGON(tg->Tess.global_tessobj);
1167 polyrep_combiner_data cbdata;
1168 //not using combinder data right now
1169 gluTessBeginPolygon( tg->Tess.global_tessobj, &cbdata); // //cbdata is for combiner
1170 gluTessBeginContour( tg->Tess.global_tessobj );
1171 } else {
1172 initind = relative_coord++;
1173 lastind = relative_coord++;
1174 }
1175
1176 i = (orig_coordIndex->p[ relative_coord + this_coord]);
1177
1178 while (i != -1) {
1179 if (!convex) {
1180 int ind;
1181 int foundContour = FALSE;
1182 /* printf ("\nwhile, i is %d this_coord %d rel coord %d\n",i,this_coord,relative_coord); */
1183
1184 /* is this a duplicate? if so, start a new contour */
1185 for (ind=tess_contour_start; ind<relative_coord; ind++) {
1186/*
1187 printf ("contour checking, comparing %d and %d, ind %d\n",
1188 orig_coordIndex->p[relative_coord + this_coord],
1189 orig_coordIndex->p[ind + this_coord],
1190 ind);
1191*/
1192 if ( orig_coordIndex->p[relative_coord + this_coord] ==
1193 orig_coordIndex->p[ind + this_coord]) {
1194 /* printf ("FOUND CONTOUR\n"); */
1195 tess_contour_start = relative_coord+1;
1196 FW_GLU_NEXT_CONTOUR(tg->Tess.global_tessobj,GLU_UNKNOWN);
1197 foundContour = TRUE;
1198 break;
1199 }
1200
1201 }
1202 if (!foundContour) {
1203 c1 = &(points[i]);
1204 tess_v[0] = c1->c[0];
1205 tess_v[1] = c1->c[1];
1206 tess_v[2] = c1->c[2];
1207 tess_vs[relative_coord] = relative_coord;
1208 /* printf ("vertex %f %f %f, index %d\n",tess_v[0], tess_v[1], tess_v[2], tess_vs[relative_coord]); */
1209 //&p->FW_RIA[p->FW_RIA_indx]
1210 //&tess_vs[relative_coord]
1211 FW_GLU_TESS_VERTEX(tg->Tess.global_tessobj,tess_v,&tess_vs[relative_coord]);
1212 }
1213
1214 relative_coord++;
1215 } else {
1216 /* take coordinates and make triangles out of them */
1217 tg->Tess.global_IFS_Coords[tg->Tess.global_IFS_Coord_count++] = initind;
1218 tg->Tess.global_IFS_Coords[tg->Tess.global_IFS_Coord_count++] = lastind;
1219 tg->Tess.global_IFS_Coords[tg->Tess.global_IFS_Coord_count++] = relative_coord;
1220 /* printf ("triangle %d %d %d\n",initind,lastind,relative_coord);*/
1221 lastind = relative_coord++;
1222 }
1223
1224 if (relative_coord + this_coord == cin) {
1225 i = -1;
1226 } else {
1227 i = (orig_coordIndex->p[ relative_coord + this_coord]);
1228 }
1229 }
1230
1231 if (!convex) {
1232 //FW_GLU_END_POLYGON(tg->Tess.global_tessobj);
1233 gluTessEndContour( tg->Tess.global_tessobj );
1234 gluTessEndPolygon( tg->Tess.global_tessobj );
1235
1236 /* Tesselated faces may have a different normal than calculated previously */
1237 /* bounds check, once again */
1238
1239 verify_global_IFS_Coords(cin);
1240
1241 IFS_check_normal (facenormals,this_face,points, this_coord, orig_coordIndex, ccw);
1242 }
1243
1244
1245 /* now store this information for the whole of the polyrep */
1246 for (i=0; i<tg->Tess.global_IFS_Coord_count; i++) {
1247 /* Triangle Coordinate */
1248 cindex [vert_ind] = (orig_coordIndex->p[this_coord+tg->Tess.global_IFS_Coords[i]]);
1249
1250 /* printf ("vertex %d gic %d cindex %d\n",vert_ind,global_IFS_Coords[i],cindex[vert_ind]); */
1251
1252 /* Vertex Normal */
1253 if(nnormals) {
1254 if (norin) {
1255 /* we have a NormalIndex */
1256 if (npv) {
1257 norindex[vert_ind] = orig_normalIndex->p[this_coord+tg->Tess.global_IFS_Coords[i]];
1258 /* printf ("norm1, index %d\n",norindex[vert_ind]);*/
1259 } else {
1260 norindex[vert_ind] = orig_normalIndex->p[this_face];
1261 /* printf ("norm2, index %d\n",norindex[vert_ind]);*/
1262 }
1263 } else {
1264 /* no normalIndex - use the coordIndex */
1265 if (npv) {
1266 norindex[vert_ind] = (orig_coordIndex->p[this_coord+tg->Tess.global_IFS_Coords[i]]);
1267 /* printf ("norm3, index %d\n",norindex[vert_ind]); */
1268 } else {
1269 norindex[vert_ind] = this_face;
1270 /* printf ("norm4, index %d\n",norindex[vert_ind]);*/
1271 }
1272 }
1273
1274 } else {
1275 if (fabs(creaseAngle) > 0.00001) {
1276 /* normalize each vertex */
1277 if (normalArraySize != INT_ID_UNDEFINED) {
1278 if (calc_normind*3 > normalArraySize) {
1279 printf ("HMMM _ NORMAL OVERFLOW\n");
1280 }
1281 }
1282
1283 normalize_ifs_face (&rep_->normal[calc_normind*3],
1284 facenormals, pointfaces, cindex[vert_ind],
1285 this_face, creaseAngle);
1286 rep_->norindex[vert_ind] = calc_normind++;
1287 } else {
1288 /* use the calculated normals */
1289 //rep_->normal[vert_ind*3+0]=(float) facenormals[this_face].x;
1290 //rep_->normal[vert_ind*3+1]=(float) facenormals[this_face].y;
1291 //rep_->normal[vert_ind*3+2]=(float) facenormals[this_face].z;
1292 veccopy3f(&rep_->normal[vert_ind*3+0],facenormals[this_face].c);
1293 rep_->norindex[vert_ind] = vert_ind;
1294 /* printf ("using calculated normals %f %f %f for face %d, vert_ind %d\n",
1295 rep_->normal[vert_ind*3+0],rep_->normal[vert_ind*3+1],
1296 rep_->normal[vert_ind*3+2],this_face,rep_->norindex[vert_ind]);
1297 */
1298 }
1299 }
1300
1301 /* Vertex Colours */
1302 if(ncolors) {
1303 if (colin) {
1304 int tmpI;
1305 /* we have a colorIndex */
1306 if (cpv) tmpI = this_coord+tg->Tess.global_IFS_Coords[i];
1307 else tmpI = this_face;
1308
1309 if (tmpI >= orig_colorIndex->n) {
1310 printf ("faceSet, colorIndex problem, %d >= %d\n", tmpI,orig_colorIndex->n);
1311 colindex[vert_ind] = 0;
1312 } else {
1313 colindex[vert_ind] = orig_colorIndex->p[tmpI];
1314 }
1315 /* printf ("col2, index %d\n",colindex[vert_ind]); */
1316
1317 } else {
1318 /* no colorIndex - use the coordIndex */
1319 if (cpv) {
1320 colindex[vert_ind] = (orig_coordIndex->p[this_coord+tg->Tess.global_IFS_Coords[i]]);
1321 /* printf ("col3, index %d\n",colindex[vert_ind]); */
1322 } else {
1323 colindex[vert_ind] = this_face;
1324 /* printf ("col4, index %d\n",colindex[vert_ind]); */
1325 }
1326 //ConsoleMessage ("color index is %d",colindex[vert_ind]);
1327 }
1328 }
1329
1330
1331 /* Texture Coordinates */
1332 if (tcin) {
1333 /* bounds checking if we run out of texCoords, just fill in with 0 */
1334 if ((this_coord+tg->Tess.global_IFS_Coords[i]) < tcin) {
1335 tcindex[vert_ind] = orig_texCoordIndex->p[this_coord+tg->Tess.global_IFS_Coords[i]];
1336 } else {
1337 tcindex[vert_ind] = 0;
1338 }
1339 /* printf ("ntexCoords,tcin, index %d\n",tcindex[vert_ind]); */
1340 } else {
1341 /* no texCoordIndex, use the Coord Index */
1342 tcindex[vert_ind] = (orig_coordIndex->p[this_coord+tg->Tess.global_IFS_Coords[i]]);
1343 /* printf ("ntexcoords, notcin, vertex %d point %d\n",vert_ind,tcindex[vert_ind]); */
1344 }
1345 // just use cindex: fogindex[vert_ind] = (orig_coordIndex->p[this_coord+tg->Tess.global_IFS_Coords[i]]);
1346
1347 /* increment index, but check for baaad errors. */
1348 if (vert_ind < (ntri*3-1)) vert_ind++;
1349 }
1350
1351 /* for the next face, we work from a new base */
1352 this_coord += relative_coord;
1353
1354 /* skip past the seperator, except if we are t the end */
1355 if (this_coord < cin)
1356 if ((orig_coordIndex->p[this_coord]) == -1) {this_coord++;}
1357 }
1358 }
1359
1360 /* we have an accurate triangle count now... */
1361 rep_->ntri = vert_ind/3;
1362 #ifdef VERBOSE
1363 printf ("make_indededfaceset, end, ntri %d\n",rep_->ntri);
1364 #endif
1365
1366 FREE_IF_NZ (tess_vs);
1367 FREE_IF_NZ (facenormals);
1368 FREE_IF_NZ (faceok);
1369 FREE_IF_NZ (pointfaces);
1370}
1371
1372#undef VERBOSE
1373
1374/********************************************************************************************/
1375/* get a valid alpha angle from that that is passed in */
1376/* asin of 1.0000 seems to fail sometimes, so */
1377double getAlpha(float ang) {
1378 if (ang >= 0.99999) return asin(0.9999);
1379 else if (ang <= -0.99999) return asin(-0.9999);
1380 return asin((double)ang);
1381}
1382
1383
1384double getGamma(double alpha, double minor) {
1385 double gamma;
1386
1387 if(APPROX(cos(alpha),0))
1388 return (double) 0;
1389 else {
1390 gamma=acos(minor / cos(alpha));
1391 if(fabs(sin(gamma)-(-minor/cos(alpha)))>fabs(sin(gamma))) gamma=-gamma;
1392 }
1393 return gamma;
1394}
1395
1396void compute_spy_spz(struct point_XYZ *spy, struct point_XYZ *spz, struct SFVec3f *spine, int nspi) {
1397 int majorX = FALSE;
1398 int majorZ = FALSE;
1399 int minorY = FALSE;
1400 int minorX = FALSE;
1401 #ifdef VERBOSE
1402 int majorY = FALSE;
1403 int minorZ = FALSE;
1404 #endif
1405 double alpha,gamma; /* angles for the rotation */
1406 int spi;
1407 float spylen;
1408 struct point_XYZ spp1 = {0.0, 0.0, 0.0};
1409
1410
1411 /* need to find the rotation from SCP[spi].y to (0 1 0)*/
1412 /* and rotate (0 0 1) and (0 1 0) to be the new y and z */
1413 /* values for all SCPs */
1414 /* I will choose rotation about the x and z axis */
1415
1416 /* search a non trivial vector along the spine */
1417 for(spi=1;spi<nspi;spi++) {
1418 VEC_FROM_CDIFF(spine[spi],spine[0],spp1);
1419 if(!APPROX(VECSQ(spp1),0))
1420 break;
1421 }
1422
1423 /* normalize the non trivial vector */
1424 spylen=1/(float) sqrt(VECSQ(spp1)); VECSCALE(spp1,spylen);
1425 #ifdef VERBOSE
1426 printf("Reference vector along spine=[%f,%f,%f]\n", spp1.x,spp1.y,spp1.z);
1427 #endif
1428
1429
1430 /* find the major and minor axes */
1431 if ((fabs(spp1.x) >= fabs(spp1.y)) && (fabs(spp1.x) >= fabs(spp1.z))) {majorX = TRUE;}
1432 else if ((fabs(spp1.y) >= fabs(spp1.x)) && (fabs(spp1.y) >= fabs(spp1.z))) {/* majorY = TRUE;*/ }
1433 else majorZ = TRUE;
1434 if ((fabs(spp1.x) <= fabs(spp1.y)) && (fabs(spp1.x) <= fabs(spp1.z))) {minorX = TRUE;}
1435 else if ((fabs(spp1.y) <= fabs(spp1.x)) && (fabs(spp1.y) <= fabs(spp1.z))) minorY = TRUE;
1436 else { /*minorZ = TRUE; */}
1437
1438 #ifdef VERBOSE
1439 printf ("major axis %d %d %d\n",majorX, majorY, majorZ);
1440 printf ("minor axis %d %d %d\n",minorX, minorY, minorZ);
1441 #endif
1442
1443 if(majorX) {
1444 /* get the angle for the x axis rotation */
1445 /* asin of 1.0000 seems to fail sometimes, so */
1446
1447 alpha = getAlpha((float)spp1.x);
1448 gamma = getGamma(alpha,minorY?spp1.y:spp1.z);
1449
1450 #ifdef VERBOSE
1451 printf("majorX: alpha=%f gamma=%f\n",alpha,gamma);
1452 #endif
1453
1454
1455 /* XXX: should we use the minor axis to determine the order of minor calculations???? */
1456 spy->y=-(cos(alpha)*(-sin(gamma)));
1457 spy->z=cos(alpha)*cos(gamma);
1458 spy->x=sin(alpha);
1459 spz->y=-(sin(alpha)*sin(gamma));
1460 spz->z=(-sin(alpha))*cos(gamma);
1461 spz->x=cos(alpha);
1462 } else if(majorZ) {
1463 /* get the angle for the z axis rotation */
1464
1465 alpha = getAlpha((float)spp1.z);
1466 gamma = getGamma(alpha,minorX?spp1.x:spp1.y);
1467
1468 #ifdef VERBOSE
1469 printf("majorZ: alpha=%f gamma=%f\n",alpha,gamma);
1470 #endif
1471 /* XXX: should we use the minor axis to determine the order of minor calculations???? */
1472 spy->y=-(cos(alpha)*(-sin(gamma)));
1473 spy->x=cos(alpha)*cos(gamma);
1474 spy->z=sin(alpha);
1475 spz->y=-(sin(alpha)*sin(gamma));
1476 spz->x=(-sin(alpha))*cos(gamma);
1477 spz->z=cos(alpha);
1478 } else {
1479 /* get the angle for the y axis rotation */
1480 if(1){
1481 /* dug9: Mar7,2013 special case: if spine is (all collinear +) parallel to
1482 local Y axis, just return and use defaults which are set up correctly */
1483 struct point_XYZ crossp;
1484 VECCP(*spy,spp1,crossp);
1485 if( veclengthd((double*)&crossp) < .001 ) return;
1486 }
1487 alpha = getAlpha((float)spp1.y);
1488 gamma = getGamma(alpha,minorX?spp1.x:spp1.z);
1489
1490 #ifdef VERBOSE
1491 printf("majorY: lpha=%f gamma=%f\n",alpha,gamma);
1492 #endif
1493 /* XXX: should we use the minor axis to determine the order of minor calculations???? */
1494 spy->x=-(cos(alpha)*(-sin(gamma)));
1495 spy->z=cos(alpha)*cos(gamma);
1496 spy->y=sin(alpha);
1497 spz->x=-(sin(alpha)*sin(gamma));
1498 spz->z=(-sin(alpha))*cos(gamma);
1499 spz->y=cos(alpha);
1500 }
1501}
1502
1503
1504
1505
1506
1507/***************************************************************
1508 stream the extrusion texture coords. We do this now because
1509 stream_polyrep does not go through the tcindexes - the old
1510 "render every triangle" method did. So, we gain in rendering
1511 speed for a little bit of post-processing here.
1512 ***************************************************************/
1513void stream_extrusion_texture_coords (struct X3D_PolyRep *rep_,
1514 float *tcoord,
1515 GLuint *tcindex) {
1516
1517 int count;
1518 int ind;
1519 float* nc;
1520
1521 /* printf ("stream_extrusion_texture_coords, have %d triangles \n",rep_->ntri); */
1522
1523 /* 2 floats per vertex, each triangle has 3 vertexes... */
1524 rep_->GeneratedTexCoords[0] = MALLOC (float *, sizeof(float) * 2 * 3 * rep_->ntri);
1525
1526 nc = rep_->GeneratedTexCoords[0];
1527
1528 /* go through - note now that the "span" is 2 floats per vertex, while the old
1529 method (used when the extrusion code was written) was to use 3 floats, but
1530 ignoring one of them. Thus the "ind*3" stuff below. Yes, we could go through
1531 and re-write the generator, but, who cares - the tcoord param is freed after
1532 the return of this, so the "waste" is only temporary.
1533 */
1534 for (count = 0; count < rep_->ntri*3; count++) {
1535 ind = tcindex[count];
1536 /* printf ("working through vertex %d - tcindex %d vertex %f %f \n",count,ind,
1537 tcoord[ind*3], tcoord[ind*3+2]); */
1538 *nc = tcoord[ind*3]; nc++; *nc = tcoord[ind*3+2]; nc++;
1539 }
1540}
1541
1542
1543void make_Extrusion(struct X3D_Extrusion *node) {
1544
1545 /*****begin of Member Extrusion */
1546 /* This code originates from the file VRMLExtrusion.pm */
1547
1548 int tcoordsize;
1549 int tcindexsize;
1550
1551 int beginCap = node->beginCap; /* beginCap flag */
1552 int endCap = node->endCap; /* endCap flag */
1553
1554 int nspi = node->spine.n; /* number of spine points */
1555 int nsec = node->crossSection.n; /* no. of points in the 2D curve
1556 but note that this is verified
1557 and coincident points thrown out */
1558
1559 int nori = node->orientation.n; /* no. of given orientators
1560 which rotate the calculated SCPs =
1561 spine-aligned cross-section planes*/
1562 int nsca = node->scale.n; /* no. of scale parameters */
1563
1564 struct SFVec3f *spine =node->spine.p; /* vector of spine vertices */
1565 struct SFVec2f *curve =node->crossSection.p; /* vector of 2D curve points */
1566 struct SFRotation *orientation=node->orientation.p;/*vector of SCP rotations*/
1567
1568 struct X3D_PolyRep *rep_=node->_intern;/*internal rep, we want to fill*/
1569
1570 /* the next variables will point at members of *rep */
1571 GLuint *cindex; /* field containing indices into
1572 the coord vector. Three together
1573 indicate which points form a
1574 triangle */
1575 float *coord; /* contains vertices building the
1576 triangles as x y z values */
1577
1578 float *tcoord; /* contains vertices building the
1579 textures as x y z values */
1580
1581 GLuint *tcindex; /* field containing texture indices
1582 for the vertex. */
1583
1584 int ntri = 0; /* no. of triangles to be used
1585 to represent all, but the caps */
1586 int nctri=0; /* no. of triangles for both caps*/
1587 int max_ncoord_add=0; /* max no. of add coords */
1588 int ncoord_add=0; /* no. off added coords */
1589 int ncoord=0; /* no. of used coords */
1590
1591 int ncolinear_at_begin=0; /* no. of triangles which need
1592 to be skipped, because curve-points
1593 are in one line at start of curve*/
1594 int ncolinear_at_end=0; /* no. of triangles which need
1595 to be skipped, because curve-points
1596 are in one line at end of curve*/
1597
1598 int spi,sec,triind,pos_of_last_zvalue; /* help variables */
1599 int next_spi, prev_spi;
1600 int t; /* another loop var */
1601
1602
1603 int circular = FALSE; /* is spine closed? */
1604 int tubular=FALSE; /* is the 2D curve closed? */
1605 int spine_is_one_vertex; /* only one real spine vertix */
1606
1607 float spxlen,spylen,spzlen; /* help vars for scaling */
1608
1609 /* def:struct representing SCPs */
1610 struct SCP { /* spine-aligned cross-section plane*/
1611 struct point_XYZ y; /* y axis of SCP */
1612 struct point_XYZ z; /* z axis of SCP */
1613 int prev,next; /* index in SCP[]
1614 prev/next different vertix for
1615 calculation of this SCP */
1616 };
1617
1618 struct SCP *SCP; /* dyn. vector rep. the SCPs */
1619
1620 struct point_XYZ spm1,spp1,spy,spz,spx; /* help vertix vars */
1621
1622 int tci_ct; /* Tex Gen index counter */
1623
1624 /* variables for calculating smooth normals */
1625 int HAVETOSMOOTH;
1626 //struct point_XYZ *facenormals = 0;
1627 struct SFVec3f *facenormals = NULL;
1628 int *pointfaces = 0;
1629 int *defaultface = 0;
1630 int this_face = 0; /* always counts up */
1631 int tmp;
1632 float creaseAngle = node->creaseAngle;
1633 int ccw = node->ccw;
1634 int end_of_sides; /* for triangle normal generation,
1635 keep track of where the sides end
1636 and caps begin */
1637
1638 /* variables for begin/endcap S,T mapping for textures */
1639 float *beginVals;
1640 float *endVals;
1641 struct SFVec2f *crossSection;
1642
1643 #ifdef VERBOSE
1644 printf ("VRMLExtrusion.pm start\n");
1645 #endif
1646
1647 /***********************************************************************
1648 *
1649 * Copy and verify cross section - remove coincident points (yes, virginia,
1650 * one of the NIST tests has this - the pie-shaped convex one
1651 *
1652 ************************************************************************/
1653/*FIXME:
1654 to prevent a crash with script generated data
1655*/
1656
1657 if (nspi < 1) return;
1658
1659 /* is there anything to this Extrusion??? */
1660 if (nsec < 1) {
1661 rep_->ntri=0;
1662 return;
1663 } else {
1664 int tmp1, temp_indx;
1665 int increment, currentlocn;
1666
1667 crossSection = MALLOC(struct SFVec2f *, sizeof(crossSection)*nsec*2);
1668
1669
1670 currentlocn = 0;
1671 for (tmp1=0; tmp1<nsec; tmp1++) {
1672 /* save this crossSection */
1673 crossSection[currentlocn].c[0] = curve[tmp1].c[0];
1674 crossSection[currentlocn].c[1] = curve[tmp1].c[1];
1675
1676 /* assume that it is not duplicated */
1677 increment = 1;
1678
1679 for (temp_indx=0; temp_indx<currentlocn; temp_indx++) {
1680 if ((APPROX(crossSection[currentlocn].c[0],crossSection[temp_indx].c[0])) &&
1681 (APPROX(crossSection[currentlocn].c[1],crossSection[temp_indx].c[1]))) {
1682 /* maybe we have a closed curve, so points SHOULD be the same */
1683 if ((temp_indx != 0) && (tmp1 != (nsec-1))) {
1684 /* printf ("... breaking; increment = 0\n");*/
1685 increment = 0;
1686 break;
1687 } else {
1688 /* printf ("... we are tubular\n");*/
1689 tubular = TRUE;
1690 }
1691 }
1692 }
1693 /* increment the crossSection index, unless it was duplicated */
1694 currentlocn += increment;
1695 }
1696
1697 #ifdef VERBOSE
1698 printf ("we had nsec %d coords, but now we have %d\n",nsec,currentlocn);
1699 #endif
1700
1701 nsec = currentlocn;
1702 }
1703
1704
1705 /* now that we have removed possible coincident vertices, we can calc ntris */
1706 ntri = 2 * (nspi-1) * (nsec-1);
1707
1708 #ifdef VERBOSE
1709 printf ("so, we have ntri %d nspi %d nsec %d\n",ntri,nspi,nsec);
1710 #endif
1711
1712 /* check if the spline is closed */
1713
1714 circular = APPROX(spine[0].c[0], spine[nspi-1].c[0]) &&
1715 APPROX(spine[0].c[1], spine[nspi-1].c[1]) &&
1716 APPROX(spine[0].c[2], spine[nspi-1].c[2]);
1717
1718 #ifdef VERBOSE
1719 printf ("tubular %d circular %d\n",tubular, circular);
1720 #endif
1721
1722
1723 /************************************************************************
1724 * calc number of triangles per cap, if caps are enabled and possible
1725 */
1726
1727 /* if we are both circular and tubular, we ignore any caps */
1728 if (circular && tubular) {
1729 beginCap = FALSE;
1730 endCap = FALSE;
1731 #ifdef VERBOSE
1732 printf ("Extrusion, turning off caps \n");
1733 #endif
1734 }
1735
1736 if(beginCap||endCap) {
1737 if(tubular?nsec<4:nsec<3) {
1738 freewrlDie("Only two real vertices in crossSection. Caps not possible!");
1739 }
1740
1741 if(tubular) nctri=nsec-2;
1742 else nctri=nsec-1;
1743
1744 #ifdef VERBOSE
1745 printf ("nsec = %d, ntri = %d nctri = %d\n",nsec, ntri,nctri);
1746 #endif
1747
1748
1749 /* check if there are colinear points at the beginning of the curve*/
1750 sec=0;
1751 while(sec+2<=nsec-1 &&
1752 /* to find out if two vectors a and b are colinear,
1753 try a.x*b.y=a.y*b.x */
1754
1755 APPROX(0, (crossSection[sec+1].c[0]-crossSection[0].c[0])
1756 *(crossSection[sec+2].c[1]-crossSection[0].c[1])
1757 - (crossSection[sec+1].c[1]-crossSection[0].c[1])
1758 *(crossSection[sec+2].c[0]-crossSection[0].c[0]))
1759 ) ncolinear_at_begin++, sec++;
1760
1761 /* check if there are colinear points at the end of the curve
1762 in line with the very first point, because we want to
1763 draw the triangle to there. */
1764 sec=tubular?(nsec-2):(nsec-1);
1765 while(sec-2>=0 &&
1766 APPROX(0, (crossSection[sec ].c[0]-crossSection[0].c[0])
1767 *(crossSection[sec-1].c[1]-crossSection[0].c[1])
1768 - (crossSection[sec ].c[1]-crossSection[0].c[1])
1769 *(crossSection[sec-1].c[0]-crossSection[0].c[0]))
1770 ) ncolinear_at_end++,sec--;
1771
1772 nctri-= ncolinear_at_begin+ncolinear_at_end;
1773
1774 if(nctri<1) {
1775 /* no triangle left :( */
1776 freewrlDie("All in crossSection points colinear. Caps not possible!");
1777 }
1778
1779 /* so we have calculated nctri for one cap, but we might have two*/
1780 nctri= ((beginCap)?nctri:0) + ((endCap)?nctri:0) ;
1781 }
1782
1783 /* if we have non-convex polygons, we might need a few triangles more */
1784 /* The unused memory will be freed with realloc later */
1785 if(!node->convex) {
1786
1787 max_ncoord_add=(nspi-1)*(nsec-1) /* because of intersections */
1788 +nctri; /* because of cap tesselation */
1789 nctri*=2; /* we might need more trigs for the caps */
1790 }
1791
1792 /************************************************************************
1793 * prepare for filling *rep
1794 */
1795
1796 rep_->ccw = 1;
1797
1798 rep_->ntri = ntri + nctri; /* Thats the no. of triangles representing
1799 the whole Extrusion Shape. */
1800
1801 /* get some memory */
1802 cindex = rep_->cindex = MALLOC(GLuint *, sizeof(*(rep_->cindex))*3*(rep_->ntri));
1803 coord = rep_->actualCoord = MALLOC(float *, sizeof(*(rep_->actualCoord))*(nspi*nsec+max_ncoord_add)*3);
1804 rep_->normal = MALLOC(float *, sizeof(*(rep_->normal))*3*(rep_->ntri)*3);
1805 rep_->norindex = MALLOC(GLuint *, sizeof(*(rep_->norindex))*3*(rep_->ntri));
1806
1807 /* face normals - one face per quad (ie, 2 triangles) */
1808 /* have to make sure that if nctri is odd, that we increment by one */
1809
1810
1811 //facenormals = MALLOC(struct point_XYZ *, sizeof(*facenormals)*(rep_->ntri+1)/2);
1812 facenormals = MALLOC(struct SFVec3f *, sizeof(struct SFVec3f)*(rep_->ntri+1)/2);
1813
1814 /* for each triangle vertex, tell me which face(s) it is in */
1815 pointfaces = MALLOC(int *, sizeof(*pointfaces)*POINT_FACES*3*rep_->ntri);
1816
1817 /* for each triangle, it has a defaultface... */
1818 defaultface = MALLOC(int *, sizeof(*defaultface)*rep_->ntri);
1819
1820
1821 /*memory for the SCPs. Only needed in this function. Freed later */
1822 SCP = MALLOC(struct SCP *, sizeof(struct SCP)*nspi);
1823
1824 /* so, we now have to worry about textures. */
1825 /* XXX note - this over-estimates; realloc to be exact */
1826
1827 tcoordsize = (nctri + (ntri*2))*3;
1828
1829 #ifdef VERBOSE
1830 printf ("tcoordsize is %d\n",tcoordsize);
1831 # endif
1832
1833 FREE_IF_NZ (rep_->GeneratedTexCoords[0]);
1834 FREE_IF_NZ (rep_->tcindex);
1835
1836 tcoord = MALLOC(float *, sizeof(*(rep_->GeneratedTexCoords[0]))*tcoordsize);
1837
1838 tcindexsize = rep_->ntri*3;
1839 #ifdef VERBOSE
1840 printf ("tcindexsize %d\n",tcindexsize);
1841 #endif
1842
1843 tcindex = MALLOC(GLuint *, sizeof(*(rep_->tcindex))*tcindexsize);
1844
1845 /* keep around cross section info for tex coord mapping */
1846 beginVals = MALLOC(float *, sizeof(float) * 2 * (nsec+1)*100);
1847 endVals = MALLOC(float *, sizeof(float) * 2 * (nsec+1)*100);
1848
1849 memset((void *)tcindex,0,tcindexsize*sizeof(*(rep_->tcindex)));
1850 /* printf ("zeroing tcindex\n");*/
1851 /* { int i; for (i=0; i<tcindexsize; i++) { tcindex[i]=0; } }*/
1852
1853 /* Normal Generation Code */
1854 HAVETOSMOOTH = (fabs(creaseAngle)>0.0001);
1855 for (tmp = 0; tmp < 3*rep_->ntri; tmp++) {
1856 pointfaces[tmp*POINT_FACES]=0;
1857 }
1858
1859
1860 /************************************************************************
1861 * calculate all SCPs
1862 */
1863
1864 spine_is_one_vertex=0;
1865
1866 /* fill the prev and next values in the SCP structs first
1867 *
1868 * this is so complicated, because spine vertices can be the same
1869 * They should have exactly the same SCP, therefore only one of
1870 * an group of sucessive equal spine vertices (now called SESVs)
1871 * must be used for calculation.
1872 * For calculation the previous and next different spine vertex
1873 * must be known. We save that info in the prev and next fields of
1874 * the SCP struct.
1875 * Note: We have start and end SESVs which will be treated differently
1876 * depending on whether the spine is closed or not
1877 *
1878 */
1879
1880 for(spi=0; spi<nspi;spi++){
1881 for(next_spi=spi+1;next_spi<nspi;next_spi++) {
1882 VEC_FROM_CDIFF(spine[spi],spine[next_spi],spp1);
1883 if(!APPROX(VECSQ(spp1),0))
1884 break;
1885 }
1886 if(next_spi<nspi) SCP[next_spi].prev=next_spi-1;
1887
1888 #ifdef VERBOSE
1889 printf("spi=%d next_spi=%d\n",spi,next_spi);
1890 #endif
1891
1892 prev_spi=spi-1;
1893 SCP[spi].next=next_spi;
1894 SCP[spi].prev=prev_spi;
1895
1896 while(next_spi>spi+1) { /* fill gaps */
1897 spi++;
1898 SCP[spi].next=next_spi;
1899 SCP[spi].prev=prev_spi;
1900 }
1901 }
1902 /* now: start-SEVS .prev fields contain -1 */
1903 /* and end-SEVS .next fields contain nspi */
1904
1905
1906 /* calculate the SCPs now... */
1907
1908 #ifdef VERBOSE
1909 printf (" SCP[0].next = %d, nspi = %d\n",SCP[0].next,nspi);
1910 #endif
1911
1912
1913
1914 if(SCP[0].next==nspi) {
1915 spine_is_one_vertex=1;
1916 #ifdef VERBOSE
1917 printf("All spine vertices are the same!\n");
1918 #endif
1919
1920 /* initialize all y and z values with zero, they will */
1921 /* be treated as colinear case later then */
1922 SCP[0].z.x=0; SCP[0].z.y=0; SCP[0].z.z=0;
1923 SCP[0].y=SCP[0].z;
1924 for(spi=1;spi<nspi;spi++) {
1925 SCP[spi].y=SCP[0].y;
1926 SCP[spi].z=SCP[0].z;
1927 }
1928 }else{
1929 #ifdef VERBOSE
1930 for(spi=0;spi<nspi;spi++) {
1931 printf("SCP[%d].next=%d, SCP[%d].prev=%d\n",
1932 spi,SCP[spi].next,spi,SCP[spi].prev);
1933 }
1934 #endif
1935
1936 /* find spine vertix different to the first spine vertix */
1937 spi=0;
1938 while(SCP[spi].prev==-1) spi++;
1939
1940 /* find last spine vertix different to the last */
1941 t=nspi-1;
1942 while(SCP[t].next==nspi) t--;
1943
1944 #ifdef VERBOSE
1945 printf ("now, spi = %d, t = %d\n",spi,t);
1946 #endif
1947
1948 /* for all but the first + last really different spine vertix */
1949 /* add case for then there are only 2 spines, and spi is already */
1950 /* spi is already greater than t... JAS */
1951
1952 if (spi > t) {
1953 /* calc y */
1954 VEC_FROM_CDIFF(spine[1],spine[0],SCP[0].y);
1955 /* calc z */
1956 VEC_FROM_CDIFF(spine[1],spine[0],spp1);
1957 if(0){
1958 VEC_FROM_CDIFF(spine[1],spine[0],spm1);
1959 VECCP(spp1,spm1,SCP[1].z);
1960 }
1961 if(1){
1962 //dug9 Mar7,2013 from specs
1963 // http://www.web3d.org/files/specifications/19775-1/V3.2/Part01/components/geometry3D.html#Extrusion
1964 //in 13.3.5.4 Special Cases "
1965 //If the entire spine is collinear, the SCP is computed by finding
1966 //the rotation of a vector along the positive Y-axis (v1) to the vector
1967 //formed by the spine points (v2). The Y=0 plane is then rotated by this value.
1968 struct point_XYZ Yaxis; //scene local Y axis (up)
1969 double dlen_cp;
1970 Yaxis.x = 0.0;
1971 Yaxis.y = 1.0;
1972 Yaxis.z = 0.0;
1973 VECCP(spp1,Yaxis,SCP[1].z);
1974 //but what if the Yaxis is aligned pretty much to the spine axis?
1975 //then the cross product will be zero. We want a unit vector. So use Zaxis.
1976 dlen_cp = veclengthd((double*)&(SCP[1].z));
1977 if( dlen_cp < .001 )
1978 {
1979 SCP[1].z.x = 0.0;
1980 SCP[1].z.y = 0.0;
1981 SCP[1].z.z = 1.0; //align z to local scene Z axis, like flux, cortona, white_dune, blaxxun, cosmo
1982 }
1983 }
1984 #ifdef VERBOSE
1985 printf ("just calculated z for spi 0\n");
1986 printf("SCP[0].y=[%f,%f,%f], SCP[1].z=[%f,%f,%f]\n",
1987 SCP[0].y.x,SCP[0].y.y,SCP[0].y.z,
1988 SCP[1].z.x,SCP[1].z.y,SCP[1].z.z);
1989 #endif
1990 }
1991
1992 else {
1993 for(; spi<=t; spi++) {
1994 /* calc y */
1995 VEC_FROM_CDIFF(spine[SCP[spi].next],spine[SCP[spi].prev],SCP[spi].y);
1996 /* calc z */
1997 VEC_FROM_CDIFF(spine[SCP[spi].next],spine[spi],spp1);
1998 VEC_FROM_CDIFF(spine[SCP[spi].prev],spine[spi],spm1);
1999 VECCP(spp1,spm1,SCP[spi].z);
2000 #ifdef VERBOSE
2001 printf ("just calculated z for spi %d\n",spi);
2002 #endif
2003 }
2004 }
2005
2006 if(circular) {
2007 #ifdef VERBOSE
2008 printf ("we are circular\n");
2009 #endif
2010 /* calc y for first SCP */
2011 VEC_FROM_CDIFF(spine[SCP[0].next],spine[SCP[nspi-1].prev],SCP[0].y);
2012 /* the last is the same as the first */
2013 SCP[nspi-1].y=SCP[0].y;
2014
2015 /* calc z */
2016 VEC_FROM_CDIFF(spine[SCP[0].next],spine[0],spp1);
2017 VEC_FROM_CDIFF(spine[SCP[nspi-1].prev],spine[0],spm1);
2018 VECCP(spp1,spm1,SCP[0].z);
2019 /* the last is the same as the first */
2020 SCP[nspi-1].z=SCP[0].z;
2021
2022 } else {
2023 #ifdef VERBOSE
2024 printf ("we are not circular\n");
2025 #endif
2026
2027 /* calc y for first SCP */
2028 VEC_FROM_CDIFF(spine[SCP[0].next],spine[0],SCP[0].y);
2029
2030 /* calc y for the last SCP */
2031 /* in the case of 2, nspi-1 = 1, ...prev = 0 */
2032 VEC_FROM_CDIFF(spine[nspi-1],spine[SCP[nspi-1].prev],SCP[nspi-1].y);
2033
2034 /* z for the start SESVs is the same as for the next SCP */
2035 SCP[0].z=SCP[SCP[0].next].z;
2036 /* z for the last SCP is the same as for the one before the last*/
2037 SCP[nspi-1].z=SCP[SCP[nspi-1].prev].z;
2038
2039 #ifdef VERBOSE
2040 printf("SCP[0].y=[%f,%f,%f], SCP[0].z=[%f,%f,%f]\n",
2041 SCP[0].y.x,SCP[0].y.y,SCP[0].y.z,
2042 SCP[0].z.x,SCP[0].z.y,SCP[0].z.z);
2043 printf("SCP[1].y=[%f,%f,%f], SCP[1].z=[%f,%f,%f]\n",
2044 SCP[1].y.x,SCP[1].y.y,SCP[1].y.z,
2045 SCP[1].z.x,SCP[1].z.y,SCP[1].z.z);
2046 #endif
2047 } /* else */
2048
2049 /* fill the other start SESVs SCPs*/
2050 spi=1;
2051 while(SCP[spi].prev==-1) {
2052 SCP[spi].y=SCP[0].y;
2053 SCP[spi].z=SCP[0].z;
2054 spi++;
2055 }
2056 /* fill the other end SESVs SCPs*/
2057 t=nspi-2;
2058 while(SCP[t].next==nspi) {
2059 SCP[t].y=SCP[nspi-1].y;
2060 SCP[t].z=SCP[nspi-1].z;
2061 t--;
2062 }
2063
2064 } /* else */
2065
2066
2067 /* We have to deal with colinear cases, what means z=0 */
2068 pos_of_last_zvalue=-1; /* where a zvalue is found */
2069 for(spi=0;spi<nspi;spi++) {
2070 if(pos_of_last_zvalue>=0) { /* already found one? */
2071 if(APPROX(VECSQ(SCP[spi].z),0))
2072 SCP[spi].z= SCP[pos_of_last_zvalue].z;
2073
2074 pos_of_last_zvalue=spi;
2075 } else
2076 if(!APPROX(VECSQ(SCP[spi].z),0)) {
2077 /* we got the first, fill the previous */
2078 #ifdef VERBOSE
2079 printf("Found z-Value!\n");
2080 #endif
2081
2082 for(t=spi-1; t>-1; t--)
2083 SCP[t].z=SCP[spi].z;
2084 pos_of_last_zvalue=spi;
2085 }
2086 }
2087
2088 #ifdef VERBOSE
2089 printf("pos_of_last_zvalue=%d\n",pos_of_last_zvalue);
2090 #endif
2091
2092
2093 /* z axis flipping, if VECPT(SCP[i].z,SCP[i-1].z)<0 */
2094 /* we can do it here, because it is not needed in the all-colinear case */
2095 for(spi=(circular?2:1);spi<nspi;spi++) {
2096 if(VECPT(SCP[spi].z,SCP[spi-1].z)<0) {
2097 VECSCALE(SCP[spi].z,-1);
2098 #ifdef VERBOSE
2099 printf("Extrusion.GenPloyRep: Flipped axis spi=%d\n",spi);
2100 #endif
2101 }
2102 } /* for */
2103
2104 /* One case is missing: whole spine is colinear */
2105 if(pos_of_last_zvalue==-1) {
2106
2107 #ifdef VERBOSE
2108 printf("Extrusion.GenPloyRep:Whole spine is colinear!\n");
2109 #endif
2110
2111 /* this is the default, if we don`t need to rotate */
2112 spy.x=0; spy.y=1; spy.z=0;
2113 spz.x=0; spz.y=0; spz.z=1;
2114
2115 if(!spine_is_one_vertex) {
2116 compute_spy_spz(&spy,&spz,spine,nspi);
2117 }
2118
2119 #ifdef VERBOSE
2120 printf ("so, spy [%f %f %f], spz [%f %f %f]\n", spy.x, spy.y,spy.z, spz.x, spz.y, spz.z);
2121 #endif
2122
2123 /* apply new y and z values to all SCPs */
2124 for(spi=0;spi<nspi;spi++) {
2125 SCP[spi].y=spy;
2126 SCP[spi].z=spz;
2127 }
2128
2129 } /* if all colinear */
2130
2131 #ifdef VERBOSE
2132 for(spi=0;spi<nspi;spi++) {
2133 printf("SCP[%d].y=[%f,%f,%f], SCP[%d].z=[%f,%f,%f]\n",
2134 spi,SCP[spi].y.x,SCP[spi].y.y,SCP[spi].y.z,
2135 spi,SCP[spi].z.x,SCP[spi].z.y,SCP[spi].z.z);
2136 }
2137 #endif
2138
2139
2140 /************************************************************************
2141 * calculate the coords
2142 */
2143
2144 /* test for number of scale and orientation parameters */
2145 if(nsca>1 && nsca <nspi)
2146 printf("Extrusion.GenPolyRep: Warning!\n"
2147 "\tNumber of scaling parameters do not match the number of spines!\n"
2148 "\tWill revert to using only the first scale value.\n");
2149
2150 if(nori>1 && nori <nspi)
2151 printf("Extrusion.GenPolyRep: Warning!\n"
2152 "\tNumber of orientation parameters "
2153 "do not match the number of spines!\n"
2154 "\tWill revert to using only the first orientation value.\n");
2155
2156
2157 for(spi = 0; spi<nspi; spi++) {
2158 double m[3][3]; /* space for the rotation matrix */
2159 spy=SCP[spi].y;
2160 spz=SCP[spi].z;
2161 VECCP(spy,spz,spx);
2162 spylen = 1/(float)sqrt(VECSQ(spy)); VECSCALE(spy, spylen);
2163 spzlen = 1/(float)sqrt(VECSQ(spz)); VECSCALE(spz, spzlen);
2164 spxlen = 1/(float)sqrt(VECSQ(spx)); VECSCALE(spx, spxlen);
2165
2166 /* rotate spx spy and spz */
2167 if(nori) {
2168 int ori = (nori==nspi ? spi : 0);
2169
2170 if(IS_ROTATION_VEC_NOT_NORMAL(orientation[ori]))
2171 printf("Extrusion.GenPolyRep: Warning!\n"
2172 "\tRotationvector #%d not normal!\n"
2173 "\tWon`t correct it, because it is bad VRML`97.\n",
2174 ori+1);
2175
2176 MATRIX_FROM_ROTATION(orientation[ori],m);
2177 VECMM(m,spx);
2178 VECMM(m,spy);
2179 VECMM(m,spz);
2180 }
2181
2182 for(sec = 0; sec<nsec; sec++) {
2183 struct point_XYZ point;
2184 float ptx = crossSection[sec].c[0];
2185 float ptz = crossSection[sec].c[1];
2186 if(nsca) {
2187 int sca = (nsca==nspi ? spi : 0);
2188 ptx *= node->scale.p[sca].c[0];
2189 ptz *= node->scale.p[sca].c[1];
2190 }
2191 point.x = ptx;
2192 point.y = 0;
2193 point.z = ptz;
2194
2195 /* printf ("working on sec %d of %d, spine %d of %d\n", sec, nsec, spi, nspi);*/
2196
2197
2198 /* texture mapping for caps - keep vals around */
2199 if (spi == 0) { /* begin cap vertices */
2200 /* printf ("begin cap vertecies index %d %d \n", sec*2+0, sec*2+1); */
2201
2202 beginVals[sec*2+0] = ptx;
2203 beginVals[sec*2+1] = ptz;
2204 } else if (spi == (nspi-1)) { /* end cap vertices */
2205 /* printf ("end cap vertecies index %d %d size %d\n", sec*2+0, sec*2+1, 2 * (nsec+1));*/
2206 endVals[(sec*2)+0]=ptx;
2207 endVals[(sec*2)+1]=ptz;
2208 }
2209
2210 /* printf ("coord index %x sec %d spi %d nsec %d\n",*/
2211 /* &coord[(sec+spi*nsec)*3+0], sec, spi,nsec);*/
2212
2213 coord[(sec+spi*nsec)*3+0] =
2214 (float)(spx.x * point.x + spy.x * point.y + spz.x * point.z)
2215 + node->spine.p[spi].c[0];
2216 coord[(sec+spi*nsec)*3+1] =
2217 (float)(spx.y * point.x + spy.y * point.y + spz.y * point.z)
2218 + node->spine.p[spi].c[1];
2219 coord[(sec+spi*nsec)*3+2] =
2220 (float)(spx.z * point.x + spy.z * point.y + spz.z * point.z)
2221 + node->spine.p[spi].c[2];
2222
2223 } /* for(sec */
2224 } /* for(spi */
2225 ncoord=nsec*nspi;
2226
2227
2228 /* freeing SCP coordinates. not needed anymore. */
2229 FREE_IF_NZ (SCP);
2230
2231 /************************************************************************
2232 * setting the values of *cindex to the right coords
2233 */
2234
2235 triind = 0;
2236 {
2237 int x,z;
2238 int A,B,C,D; /* should referr to the four vertices of the polygon
2239 (hopefully) counted counter-clockwise, like
2240
2241 D----C
2242 | |
2243 | |
2244 | |
2245 A----B
2246
2247 */
2248 int Atex, Btex, Ctex, Dtex, Etex, Ftex; /* Tex Coord points */
2249
2250 struct point_XYZ ac,bd, /* help vectors */
2251 ab,cd; /* help vectors for testing intersection */
2252 int E,F; /* third point to be used for the triangles*/
2253 double u,r, /* help variables for testing intersection */
2254 denominator, /* ... */
2255 numerator; /* ... */
2256
2257 #ifdef VERBOSE
2258 printf("Coords: \n");
2259
2260 for(x=0; x<nsec; x++) {
2261 for(z=0; z<nspi; z++) {
2262 int xxx = 3*(x+z*nsec);
2263 printf("coord: %d [%f %f %f] ",(x+z*nsec),
2264 coord[xxx], coord[xxx+1], coord[xxx+2]);
2265
2266 }
2267 printf("\n");
2268 }
2269 printf("\n");
2270 #endif
2271
2272
2273 /* Now, lay out the spines/sections, and generate triangles */
2274 //register_Polyrep_combiner(); //default, component_text resets to this after compiling its text
2275 for(x=0; x<nsec-1; x++) {
2276 for(z=0; z<nspi-1; z++) {
2277 A=x+z*nsec;
2278 B=(x+1)+z*nsec;
2279 C=(x+1)+(z+1)*nsec;
2280 D= x+(z+1)*nsec;
2281
2282 /* texture mapping coords */
2283 Atex = A; Btex = B; Ctex = C; Dtex = D;
2284
2285 /* if we are circular, check to see if this is the first tri, or the last */
2286 /* the vertexes are identical, but for smooth normal calcs, make the */
2287 /* indexes the same, too */
2288 /* note, we dont touch tex coords here. */
2289 /* printf ("x %d z %d nsec %d nspi %d\n",x,z,nsec,nspi);*/
2290
2291 if (tubular) {
2292 /* printf ("tubular, x %d nsec %d this_face %d\n",x,nsec,this_face);*/
2293 if (x==(nsec-2)) {
2294 B -=(x+1);
2295 C -=(x+1);
2296 }
2297 }
2298
2299 if (circular) {
2300 if (z==(nspi-2)) {
2301 /* last row in column, assume z=nspi-2, subtract this off */
2302 C -= (z+1)*nsec;
2303 D -= (z+1)*nsec;
2304 }
2305 }
2306
2307 /* calculate the distance A-C and see, if it is smaller as B-D */
2308 VEC_FROM_COORDDIFF(coord,C,coord,A,ac);
2309 VEC_FROM_COORDDIFF(coord,D,coord,B,bd);
2310
2311 if(sqrt(VECSQ(ac))>sqrt(VECSQ(bd))) {
2312 E=B; F=D; Etex=Btex; Ftex=Dtex;
2313 } else {
2314 E=C; F=A; Etex=Ctex; Ftex=Atex;
2315 }
2316
2317 /* if concave polygons are expected, we also expect intersecting ones
2318 so we are testing, whether A-B and D-C intersect */
2319 if(!node->convex) {
2320 VEC_FROM_COORDDIFF(coord,B,coord,A,ab);
2321 VEC_FROM_COORDDIFF(coord,D,coord,C,cd);
2322 /* ca=-ac */
2323 #ifdef VERBOSE
2324 printf("ab=[%f,%f,%f],cd=[%f,%f,%f]\n",
2325 ab.x,ab.y,ab.z,cd.x,cd.y,cd.z);
2326 printf("Orig: %d %d [%f %f %f] [%f %f %f] (%d, %d, %d) \n",
2327 D, C,
2328 coord[D*3], coord[D*3+1], coord[D*3+2],
2329 coord[C*3], coord[C*3+1], coord[C*3+2],
2330 ncoord, nsec, nspi
2331 );
2332 #endif
2333
2334 denominator= ab.y*cd.x-ab.x*cd.y;
2335 numerator = (-ac.x)*cd.y-(-ac.y)*cd.x;
2336
2337 r=u=-1;
2338 if(!APPROX(denominator,0)) {
2339 u=numerator/denominator;
2340 r=((-ac.x)*ab.y-(-ac.y)*ab.x)/denominator;
2341 } else {
2342 /* lines still may be coincident*/
2343 if(APPROX(numerator,0)) {
2344 /* we have to calculate u and r using the z coord*/
2345 denominator=ab.z*cd.x-ab.x*cd.z;
2346 numerator = (-ac.x)*cd.z-(-ac.z)*cd.x;
2347 if(!APPROX(denominator,0)) {
2348 u=numerator/denominator;
2349 r=((-ac.x)*ab.y-(-ac.y)*ab.x)/denominator;
2350 }
2351 }
2352 } /* else */
2353 #ifdef VERBOSE
2354 printf("u=%f, r=%f\n",u,r);
2355 #endif
2356
2357 if(u>=0 && u<=1 && r>=0 && r<=1
2358 && APPROX((-ac.x)+u*ab.x,r*cd.x)
2359 && APPROX((-ac.y)+u*ab.y,r*cd.y)
2360 && APPROX((-ac.z)+u*ab.z,r*cd.z)) {
2361
2362 #ifdef VERBOSE
2363 printf("Intersection found at P=[%f,%f,%f]!\n",
2364 coord[A*3]+u*ab.x,
2365 coord[A*3+1]+u*ab.y,
2366 coord[A*3+2]+u*ab.y
2367 );
2368 #endif
2369
2370 coord[(ncoord)*3 ]=coord[A*3 ]+(float)(u*ab.x);
2371 coord[(ncoord)*3+1]=coord[A*3+1]+(float)(u*ab.y);
2372 coord[(ncoord)*3+2]=coord[A*3+2]+(float)(u*ab.z);
2373 E=ncoord;
2374 F=ncoord;
2375 ncoord_add++;
2376 ncoord++;
2377 }
2378
2379 }
2380
2381 /* printf ("tcindex %d\n",tcindex);*/
2382 /* printf ("Triangle1 %d %d %d\n",D,A,E);*/
2383 /* first triangle calculate pointfaces, etc, for this face */
2384 Elev_Tri(triind*3, this_face, D,A,E, TRUE , rep_, facenormals, pointfaces,ccw);
2385
2386 tcindex[triind*3] = (GLuint)Dtex;
2387 tcindex[triind*3+2] = (GLuint)Etex;
2388 tcindex[triind*3+1] = (GLuint)Atex;
2389
2390 defaultface[triind] = this_face;
2391 triind++;
2392
2393 /* printf ("Triangle2 %d %d %d\n",B,C,F);*/
2394 /* second triangle - pointfaces, etc,for this face */
2395 Elev_Tri(triind*3, this_face, B, C, F, TRUE, rep_, facenormals, pointfaces,ccw);
2396
2397 tcindex[triind*3] = (GLuint)Btex;
2398 tcindex[triind*3+1] = (GLuint)Ctex;
2399 tcindex[triind*3+2] = (GLuint)Ftex;
2400
2401 if ((triind*3+2) >= tcindexsize)
2402 printf ("INTERNAL ERROR: Extrusion - tcindex size too small!\n");
2403 defaultface[triind] = this_face;
2404 triind ++;
2405 this_face ++;
2406
2407 }
2408 }
2409
2410 /* do normal calculations for the sides, here */
2411 for (tmp=0; tmp<(triind*3); tmp++) {
2412 if (HAVETOSMOOTH) {
2413 normalize_ifs_face (&rep_->normal[tmp*3],
2414 facenormals, pointfaces, cindex[tmp],
2415 defaultface[tmp/3], creaseAngle);
2416 } else {
2417 int iiface = defaultface[tmp/3];
2418 veccopy3f(&rep_->normal[tmp*3+0],facenormals[iiface].c);
2419 //rep_->normal[tmp*3+0] = (float) facenormals[defaultface[tmp/3]].x;
2420 //rep_->normal[tmp*3+1] = (float) facenormals[defaultface[tmp/3]].y;
2421 //rep_->normal[tmp*3+2] = (float) facenormals[defaultface[tmp/3]].z;
2422 }
2423 rep_->norindex[tmp] = (GLuint)tmp;
2424 }
2425 /* keep track of where the sides end, triangle count-wise, for Normal mapping */
2426 end_of_sides = triind*3;
2427
2428 /* tcindexes are TOTALLY different from sides - set this in case we are
2429 doing textures in the end caps */
2430 tci_ct = nspi*nsec;
2431
2432 if(node->convex) {
2433 int endpoint;
2434
2435 int triind_start; /* textures need 2 passes */
2436
2437 /* if not tubular, we need one more triangle */
2438 if (tubular) endpoint = nsec-3-ncolinear_at_end;
2439 else endpoint = nsec-2-ncolinear_at_end;
2440
2441
2442 /* printf ("beginCap, starting at triind %d\n",triind);*/
2443
2444 /* this is the simple case with convex polygons */
2445 if(beginCap) {
2446 triind_start = triind;
2447
2448 for(x=0+ncolinear_at_begin; x<endpoint; x++) {
2449 Elev_Tri(triind*3, this_face, 0, x+2, x+1, TRUE , rep_, facenormals, pointfaces,ccw);
2450 defaultface[triind] = this_face;
2451 Extru_tex(triind*3, tci_ct, 0 , +x+2, x+1, tcindex ,ccw,tcindexsize);
2452 triind ++;
2453 }
2454
2455 Extru_ST_map(triind_start,0+ncolinear_at_begin,endpoint,
2456 beginVals,nsec,tcindex, cindex, tcoord, tcoordsize);
2457 tci_ct+=endpoint-(0+ncolinear_at_begin);
2458 triind_start+=endpoint-(0+ncolinear_at_begin);
2459 this_face++;
2460 } /* if beginCap */
2461
2462 if(endCap) {
2463 triind_start = triind;
2464
2465 for(x=0+ncolinear_at_begin; x<endpoint; x++) {
2466 Elev_Tri(triind*3, this_face, 0 +(nspi-1)*nsec,
2467 x+1+(nspi-1)*nsec,x+2+(nspi-1)*nsec,
2468 TRUE , rep_, facenormals, pointfaces,ccw);
2469 defaultface[triind] = this_face;
2470 Extru_tex(triind*3, tci_ct, 0+(nspi-1)*nsec,
2471 x+1+(nspi-1)*nsec,
2472 x+2+(nspi-1)*nsec,
2473 tcindex,ccw,tcindexsize);
2474 triind ++;
2475 }
2476 this_face++;
2477 Extru_ST_map(triind_start,0+ncolinear_at_begin,endpoint,
2478 endVals, nsec, tcindex, cindex, tcoord, tcoordsize);
2479 } /* if endCap */
2480 /* for (tmp=0;tmp<tcindexsize; tmp++) printf ("index1D %d tcindex %d\n",tmp,tcindex[tmp]);*/
2481
2482 } else
2483 if(beginCap || endCap) {
2484 /* polygons might be concave-> do tessellation */
2485 /* XXX - no textures yet - Linux Tesselators give me enough headaches;
2486 lets wait until they are all ok before trying texture mapping */
2487
2488 /* give us some memory - this array will contain tessd triangle counts */
2489 int *tess_vs;
2490 struct SFVec3f *c1;
2491 GLDOUBLE tess_v[3];
2492 int endpoint;
2493 ttglobal tg = gglobal();
2494
2495 tess_vs=MALLOC(int *, sizeof(*(tess_vs)) * (nsec - 3 - ncolinear_at_end) * 3);
2496
2497 /* if not tubular, we need one more triangle */
2498 if (tubular) endpoint = nsec-1-ncolinear_at_end;
2499 else endpoint = nsec-ncolinear_at_end;
2500
2501
2502 if (beginCap) {
2503 tg->Tess.global_IFS_Coord_count = 0;
2504 //FW_GLU_BEGIN_POLYGON(tg->Tess.global_tessobj);
2505 gluTessBeginPolygon( tg->Tess.global_tessobj, NULL); //&cbdata );
2506 gluTessBeginContour( tg->Tess.global_tessobj );
2507
2508 for(x=0+ncolinear_at_begin; x<endpoint; x++) {
2509 /* printf ("starting tv for x %d of %d\n",x,endpoint);*/
2510 c1 = (struct SFVec3f *) &rep_->actualCoord[3*x];
2511 /* printf ("and, coords for this one are: %f %f %f\n",*/
2512 /* c1->c[0], c1->c[1],c1->c[2]);*/
2513
2514 tess_v[0] = c1->c[0]; tess_v[1] = c1->c[1]; tess_v[2] = c1->c[2];
2515 tess_vs[x] = x;
2516 FW_GLU_TESS_VERTEX(tg->Tess.global_tessobj,tess_v,&tess_vs[x]);
2517 }
2518 //FW_GLU_END_POLYGON(tg->Tess.global_tessobj);
2519 gluTessEndContour( tg->Tess.global_tessobj );
2520 gluTessEndPolygon( tg->Tess.global_tessobj );
2521
2522 verify_global_IFS_Coords(ntri*3);
2523
2524 for (x=0; x<tg->Tess.global_IFS_Coord_count; x+=3) {
2525 /* printf ("now, in 2nd for loop, x %d glob %d\n",x,*/
2526 /* global_IFS_Coord_count);*/
2527 Elev_Tri(triind*3, this_face, tg->Tess.global_IFS_Coords[x],
2528 tg->Tess.global_IFS_Coords[x+2], tg->Tess.global_IFS_Coords[x+1],
2529 TRUE , rep_, facenormals, pointfaces,ccw);
2530 defaultface[triind] = this_face;
2531 triind ++;
2532 }
2533 /* Tesselated faces may have a different normal than calculated previously */
2534 Extru_check_normal (facenormals,this_face,-1,rep_,ccw);
2535
2536 this_face++;
2537 }
2538
2539 if (endCap) {
2540 tg->Tess.global_IFS_Coord_count = 0;
2541 //FW_GLU_BEGIN_POLYGON(tg->Tess.global_tessobj);
2542 gluTessBeginPolygon( tg->Tess.global_tessobj, NULL); //&cbdata ); //cbdata is for combiner
2543 gluTessBeginContour( tg->Tess.global_tessobj );
2544
2545 for(x=0+ncolinear_at_begin; x<endpoint; x++) {
2546 c1 = (struct SFVec3f *) &rep_->actualCoord[3*(x+(nspi-1)*nsec)];
2547 tess_v[0] = c1->c[0]; tess_v[1] = c1->c[1]; tess_v[2] = c1->c[2];
2548 tess_vs[x] = x+(nspi-1)*nsec;
2549 FW_GLU_TESS_VERTEX(tg->Tess.global_tessobj,tess_v,&tess_vs[x]);
2550 }
2551 //FW_GLU_END_POLYGON(tg->Tess.global_tessobj);
2552 gluTessEndContour( tg->Tess.global_tessobj );
2553 gluTessEndPolygon( tg->Tess.global_tessobj );
2554
2555 verify_global_IFS_Coords(ntri*3);
2556
2557 for (x=0; x<tg->Tess.global_IFS_Coord_count; x+=3) {
2558 Elev_Tri(triind*3, this_face, tg->Tess.global_IFS_Coords[x],
2559 tg->Tess.global_IFS_Coords[x+1], tg->Tess.global_IFS_Coords[x+2],
2560 TRUE , rep_, facenormals, pointfaces,ccw);
2561 defaultface[triind] = this_face;
2562 triind ++;
2563 }
2564 /* Tesselated faces may have a different normal than calculated previously */
2565 Extru_check_normal (facenormals,this_face,1,rep_,ccw);
2566
2567 this_face++;
2568 }
2569
2570 /* get rid of MALLOCd memory for tess */
2571 FREE_IF_NZ (tess_vs);
2572 } /* elseif */
2573
2574 } /* end of block */
2575
2576 /* if we have tesselated, we MAY have fewer triangles than estimated, so... */
2577 rep_->ntri=triind;
2578
2579 /* for (tmp=0;tmp<tcindexsize; tmp++) printf ("index2 %d tcindex %d\n",tmp,tcindex[tmp]);*/
2580 /* do normal calculations for the caps here note - no smoothing */
2581 for (tmp=end_of_sides; tmp<(triind*3); tmp++) {
2582 int iiface = defaultface[tmp/3];
2583 veccopy3f(&rep_->normal[tmp*3+0],facenormals[iiface].c);
2584 //rep_->normal[tmp*3+0] = (float) facenormals[defaultface[tmp/3]].x;
2585 //rep_->normal[tmp*3+1] = (float) facenormals[defaultface[tmp/3]].y;
2586 //rep_->normal[tmp*3+2] = (float) facenormals[defaultface[tmp/3]].z;
2587 rep_->norindex[tmp] = (GLuint)tmp;
2588 }
2589
2590 /* do texture mapping calculations for sides */
2591 /* range check - this should NEVER happen... */
2592 if (tcoordsize <= ((nsec-1)+(nspi-1)*(nsec-1)*3+2)) {
2593 printf ("INTERNAL ERROR: Extrusion side tcoord calcs nspi %d nsec %d tcoordsize %d\n",
2594 nspi,nsec,tcoordsize);
2595 }
2596 for(sec=0; sec<nsec; sec++) {
2597 for(spi=0; spi<nspi; spi++) {
2598 /* printf ("tcoord idx %d %d %d tcoordsize %d ",*/
2599 /* (sec+spi*nsec)*3,(sec+spi*nsec)*3+1,(sec+spi*nsec)*3+2,tcoordsize);*/
2600 /* printf ("side texts sec %d spi %d\n",sec,spi);*/
2601 tcoord[(sec+spi*nsec)*3+0] = (float) sec/(nsec-1);
2602 tcoord[(sec+spi*nsec)*3+1] = 0;
2603 tcoord[(sec+spi*nsec)*3+2] = (float) spi/(nspi-1);
2604 /* printf (" %f %f\n",tcoord[(sec+spi*nsec)*3+0],tcoord[(sec+spi*nsec)*3+2]);*/
2605 }
2606 }
2607
2608 #ifdef VERBOSE
2609 printf ("done, lets free\n");
2610 #endif
2611
2612 /* we no longer need to keep normal-generating memory around */
2613 FREE_IF_NZ (defaultface);
2614 FREE_IF_NZ (pointfaces);
2615 FREE_IF_NZ (facenormals);
2616 FREE_IF_NZ (crossSection);
2617
2618 FREE_IF_NZ (beginVals);
2619 FREE_IF_NZ (endVals);
2620
2621
2622 /* stream the texture coords so that they are linear as tcindex is not used in stream_polyrep */
2623 stream_extrusion_texture_coords (rep_, tcoord, tcindex);
2624
2625 /* now that the tex coords are streamed, remove the temoporary arrays */
2626 FREE_IF_NZ (tcoord);
2627 FREE_IF_NZ (tcindex);
2628
2629
2630 #ifdef VERBOSE
2631 printf("Extrusion.GenPloyRep: triind=%d ntri=%d nctri=%d "
2632 "ncolinear_at_begin=%d ncolinear_at_end=%d\n",
2633 triind,ntri,nctri,ncolinear_at_begin,ncolinear_at_end);
2634
2635 printf ("end VRMLExtrusion.pm\n");
2636 #endif
2637
2638 /*****end of Member Extrusion */
2639}