FreeWRL / FreeX3D 4.3.0
StreamPoly.c
1/*
2
3
4???
5
6*/
7
8/****************************************************************************
9 This file is part of the FreeWRL/FreeX3D Distribution.
10
11 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
12
13 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
14 it under the terms of the GNU Lesser Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
25****************************************************************************/
26
27
28
29#include <config.h>
30#include <system.h>
31#include <display.h>
32#include <internal.h>
33
34#include <libFreeWRL.h>
35
36#include "../vrml_parser/Structs.h"
37#include "../main/headers.h"
38#include "../opengl/OpenGL_Utils.h"
39#include "../opengl/Textures.h"
40#include "../scenegraph/RenderFuncs.h"
41#include "../scenegraph/Component_Shape.h"
42#include "../opengl/Frustum.h"
43
44#include "Polyrep.h"
45
46#define NO_TEXCOORD_NODE (r->tcoordtype==0)
47
48
49static void defaultTextureMap(struct X3D_Node *p, struct X3D_PolyRep *r);
50
51/********************************************************************
52*
53* stream_polyrep
54*
55* convert a polyrep into a structure format that displays very
56* well, especially on fast graphics hardware
57*
58* many shapes go to a polyrep structure; Extrusions, ElevationGrids,
59* IndexedFaceSets, and all of the Triangle nodes.
60*
61* This is stage 2 of the polyrep build process; the first stage is
62* (for example) make_indexedfaceset(node); it creates a polyrep
63* structure.
64*
65* This stage takes that polyrep structure, and finishes it in a
66* generic fashion, and makes it "linear" so that it can be rendered
67* very quickly by the GPU.
68*
69* we ALWAYS worry about texture coords, even if this geometry does not
70* have a texture in the associated geometry node; you *never* know
71* when that Appearance node will change. Some nodes, eg ElevationGrid,
72* will automatically generate texture coordinates so they are outside
73* of this scope.
74*
75*********************************************************************/
76
77/* texture generation points... */
78//int Sindex;
79//int Tindex;
80//GLfloat minVals[3];
81//GLfloat Ssize;
82
83typedef struct pStreamPoly{
84 int Sindex;
85 int Tindex;
86 GLfloat minVals[3];
87 GLfloat Ssize;
88}* ppStreamPoly;
89void *StreamPoly_constructor(){
90 void *v = MALLOCV(sizeof(struct pStreamPoly));
91 memset(v,0,sizeof(struct pStreamPoly));
92 return v;
93}
94void StreamPoly_init(struct tStreamPoly *t){
95 //public
96 //private
97 t->prv = StreamPoly_constructor();
98
99 // JAS {ppStreamPoly p = (ppStreamPoly)t->prv;}
100}
101//ppStreamPoly p = (ppStreamPoly)gglobal()->StreamPoly.prv;
102
103/*
104static GLfloat maxVals[] = {-99999.9, -999999.9, -99999.0};
105static GLfloat Tsize = 0.0;
106static GLfloat Xsize = 0.0;
107static GLfloat Ysize = 0.0;
108static GLfloat Zsize = 0.0;
109*/
110
111/* take 3 or 4 floats, bounds check them, and put them in a destination.
112 Used for copying color X3DColorNode values over for streaming the
113 structure. */
114
115static void do_glColor4fv(struct SFColorRGBA *dest, GLfloat *param, int isRGBA) {
116 int i;
117 int pc;
118
119 if (isRGBA) pc = 4; else pc = 3;
120
121 /* if (isRGBA) printf ("do_glColor4fv, isRGBA\n"); else printf ("do_glColor4fv, NOT RGBA, setting alpha to 1\n"); */
122
123 /* parameter checks */
124 for (i=0; i<pc; i++) {
125 if ((param[i] < 0.0) || (param[i] >1.0)) {
126 param[i] = 0.5f;
127 }
128 }
129 dest->c[0] = param[0];
130 dest->c[1] = param[1];
131 dest->c[2] = param[2];
132
133 /* does this color have an alpha channel? */
134 if (isRGBA) {
135 dest->c[3] = param[3];
136 } else {
137 /* we calculate the transparency of the node. VRML 0.0 = fully visible, OpenGL 1.0 = fully visible */
138 dest->c[3] = 1.0f;
139 }
140 /* printf ("do_glColor4fv, resulting is R %f G %f B %f A %f\n",dest->c[0],dest->c[1],dest->c[2], dest->c[3]); */
141}
142
143
144void stream_polyrep(void *innode, void *coord, void *fogCoord, void *color, void *normal, struct X3D_TextureCoordinate *texCoordNode) {
145/* takes indexes from make_genericFaceSet -there are 3x number of triangles indexes-
146 and iterates over the indexes, duplicating the shared vertices, so that vertices count is 3x ntri
147 -- as is normal count, texcoord count, vertex color count
148*/
149 struct X3D_Node *node;
150 struct X3D_PolyRep *r;
151 int i, j, k, nmtexcoord;
152 int hasc;
153 //GLfloat thisTrans;
154
155 struct SFVec3f *points= NULL; int npoints=0;
156 struct SFColor *colors= NULL; int ncolors=0;
157 struct SFVec3f *normals= NULL; int nnormals=0;
158 float *fogpoints = NULL;
159 int isRGBA = FALSE;
160
161 struct X3D_Coordinate *xc;
162 //struct X3D_FogCoordinate *fc;
163 struct X3D_Color *cc;
164 struct X3D_Normal *nc;
165
166 /* new memory locations for new data */
167 GLuint *newcindex = NULL;
168 GLuint *newtcindex = NULL;
169 struct SFVec3f *newpoints = NULL;
170 float *newfog = NULL;
171 struct SFVec3f *newnorms = NULL;
172 struct SFColorRGBA *newcolors = NULL;
173 struct SFColorRGBA *oldColorsRGBA = NULL;
174 float *newTexCoords[MAX_MULTITEXTURE];
175 bool temp_points = FALSE;
176 struct Multi_Vec2f *textureCoordPoint[MAX_MULTITEXTURE];
177 int ntexdim[MAX_MULTITEXTURE];
178 char* map[MAX_MULTITEXTURE];
179 for(k=0;k<MAX_MULTITEXTURE;k++){
180 textureCoordPoint[k] = NULL;
181 newTexCoords[k] = NULL;
182 ntexdim[k] = 2;
183 map[k] = NULL; //TextureCoordinate.mapping added in web3d v4
184 }
185 nmtexcoord = 0; //number of multitextureCoordinates 0-4
186
187 /* get internal structures */
188 node = X3D_NODE(innode);
189 r = (struct X3D_PolyRep*) node->_intern;
190 r->actualFog = NULL;
191
192 #ifdef STREAM_POLY_VERBOSE
193 printf ("start spv for %p extents %lf %lf, %lf %lf, %lf %lf\n",node,
194 node->EXTENT_MIN_X,
195 node->EXTENT_MAX_X,
196 node->EXTENT_MIN_Y,
197 node->EXTENT_MAX_Y,
198 node->EXTENT_MIN_Z,
199 node->EXTENT_MAX_Z
200 );
201 #endif
202
203 /* printf ("stream_polyrep, at start, we have %d triangles texCoord %u\n",r->ntri,texCoord); */
204
205 /* does this one have any triangles here? (eg, an IFS without coordIndex) */
206 if (r->ntri==0) {
207 printf ("stream IFS, at start, this guy is empty, just returning \n");
208 return;
209 }
210
211 /* sanity check parameters, and get numbers */
212 if (coord) {
213 xc = (struct X3D_Coordinate *) coord;
214 if (xc->_nodeType != NODE_Coordinate && xc->_nodeType != NODE_GeoCoordinate ) {
215 printf ("stream_polyrep, coord expected %d, got %d\n",NODE_Coordinate, xc->_nodeType);
216 r->ntri=0;
217 return;
218 } else if(xc->_nodeType == NODE_GeoCoordinate){
219 //int i,j;
220 struct X3D_GeoCoordinate *xgc = (struct X3D_GeoCoordinate *) coord;
221 if(0)
222 {
223 temp_points = true;
224 points = MALLOC(struct SFVec3f *, sizeof(struct SFVec3f)*(xgc->point.n));
225 npoints = xgc->point.n;
226 for(i=0;i<npoints;i++)
227 {
228 for(j=0;j<3;j++)
229 points[i].c[j] = (float) xgc->point.p[i].c[j]; //point is in geographic lat/lon
230 }
231 }else{
232 points = xgc->__movedCoords.p; //moved is in GC - GO m
233 npoints = xgc->__movedCoords.n;
234 }
235 } else { points = xc->point.p; npoints = xc->point.n; }
236 }
237
238 #ifdef STREAM_POLY_VERBOSE
239 printf ("so, points is %p, npoints is %d ntri %d\n",points, npoints,r->ntri);
240 #endif
241 if(fogCoord){
242 if (((struct X3D_Node*)fogCoord)->_nodeType == NODE_FogCoordinate){
243 struct X3D_FogCoordinate * xfc = (struct X3D_FogCoordinate *)fogCoord;
244 fogpoints = xfc->depth.p;
245 }
246 }
247 if (color) {
248 cc = (struct X3D_Color *) color;
249 if ((cc->_nodeType != NODE_Color) && (cc->_nodeType != NODE_ColorRGBA)) {
250 ConsoleMessage ("stream_polyrep, expected %d got %d\n", NODE_Color, cc->_nodeType);
251 r->ntri=0;
252 return;
253 } else {
254 colors = cc->color.p;
255 ncolors = cc->color.n;
256 isRGBA = (cc->_nodeType == NODE_ColorRGBA);
257 }
258 }
259
260 if(normal) {
261 nc = (struct X3D_Normal *) normal;
262 if (nc->_nodeType != NODE_Normal) {
263 ConsoleMessage ("stream_polyrep, normal expected %d, got %d\n",NODE_Normal, nc->_nodeType);
264 r->ntri=0;
265 return;
266 } else { normals = nc->vector.p; nnormals = nc->vector.n; }
267 }
268
269 if (r->tcoordtype) {
270 if ((r->tcoordtype != NODE_TextureCoordinate) &&
271 (r->tcoordtype != NODE_TextureCoordinate3D) &&
272 (r->tcoordtype != NODE_TextureCoordinate4D) &&
273 (r->tcoordtype != NODE_MultiTextureCoordinate) &&
274 (r->tcoordtype != NODE_TextureCoordinateGenerator )) {
275 ConsoleMessage ("stream_polyrep, TexCoord expected %d, got %d\n",NODE_TextureCoordinate, r->tcoordtype);
276 r->ntri=0;
277 return;
278 }
279
280 if (r->tcoordtype == NODE_TextureCoordinate) {
281 //ConsoleMessage ("have textureCoord, point.n = %d",tc->point.n);
282 if (texCoordNode) {
283 textureCoordPoint[0] = &(texCoordNode->point);
284 nmtexcoord = 1;
285 ntexdim[0] = 2;
286 map[0] = texCoordNode->mapping ? texCoordNode->mapping->strptr : NULL;
287 }
288 }
289 if (r->tcoordtype == NODE_TextureCoordinate3D) {
290 //ConsoleMessage ("have textureCoord, point.n = %d",tc->point.n);
291 struct X3D_TextureCoordinate3D *tcn = (struct X3D_TextureCoordinate3D *)texCoordNode;
292 //we'll downcast MFVec3f to MFVec2f to get .n, .p later, and upcaste then based on nexdim
293 textureCoordPoint[0] = (struct Multi_Vec2f*) &(tcn->point);
294 nmtexcoord = 1;
295 ntexdim[0] = 3;
296 map[0] = tcn->mapping ? tcn->mapping->strptr : NULL;
297 }
298 if (r->tcoordtype == NODE_TextureCoordinate4D) {
299 //ConsoleMessage ("have textureCoord, point.n = %d",tc->point.n);
300 struct X3D_TextureCoordinate4D *tcn = (struct X3D_TextureCoordinate4D *)texCoordNode;
301 //we'll downcast MFVec3f to MFVec2f to get .n, .p later, and upcaste then based on nexdim
302 textureCoordPoint[0] =(struct Multi_Vec2f*) &(tcn->point);
303 nmtexcoord = 1;
304 ntexdim[0] = 4;
305 map[0] = tcn->mapping ? tcn->mapping->strptr : NULL;
306 }
307
308 if (r->tcoordtype == NODE_MultiTextureCoordinate) {
309 //improper hack to get at least the first multitexture coords right
310 struct X3D_MultiTextureCoordinate * mtc = (struct X3D_MultiTextureCoordinate*)texCoordNode;
311 if(mtc->texCoord.n && mtc->texCoord.p){
312 for(k=0;k<min(mtc->texCoord.n,MAX_MULTITEXTURE);k++){
313 textureCoordPoint[k] = NULL;
314 if( mtc->texCoord.p[k]->_nodeType == NODE_TextureCoordinate){
315 struct X3D_TextureCoordinate * ttcc = (struct X3D_TextureCoordinate*)mtc->texCoord.p[k];
316 textureCoordPoint[k] = &(ttcc->point);
317 ntexdim[k] = 2;
318 map[k] = ttcc->mapping ? ttcc->mapping->strptr : NULL;
319 nmtexcoord++;
320 }
321 }
322 }
323 }
324
325
326 // TextureCoordinateGenerator, make the r->texgentype match the TCGT_ definition of the field
327 if (r->tcoordtype == NODE_TextureCoordinateGenerator) {
328 struct X3D_TextureCoordinateGenerator* tcg = (struct X3D_TextureCoordinateGenerator*)texCoordNode;
329 r->texgentype = findFieldInARR((tcg)->mode->strptr, TEXTURECOORDINATEGENERATOR, TEXTURECOORDINATEGENERATOR_COUNT);
330 //ConsoleMessage("have texgen, type %d",r->texgentype);
331 map[0] = tcg->mapping ? tcg->mapping->strptr : NULL;
332 }
333 }
334
335 #ifdef STREAM_POLY_VERBOSE
336 printf ("\nstart stream_polyrep ncoords %d ncolors %d nnormals %d ntri %d\n",
337 npoints, ncolors, nnormals, r->ntri);
338 #endif
339
340
341 #ifdef STREAM_POLY_VERBOSE
342 printf ("stream polyrep, have an intern type of %d GeneratedTexCoords %p tcindex %p\n",r->tcoordtype, r->GeneratedTexCoords,r->tcindex);
343 printf ("polyv, points %p coord %p ntri %d rnormal %p nnormal %d\n",points,r->actualCoord,r->ntri,r->normal, nnormals);
344 #endif
345
346 /* Do we have any colours? Are textures, if present, not RGB? */
347 hasc = ((ncolors || r->color) && (gglobal()->RenderFuncs.last_texture_type!=TEXTURE_NO_ALPHA));
348
349
350 // if (r->GeneratedTexCoords) for (i=0; i<10; i++) printf ("start stream, tc %d gt[i] %f\n",i,r->GeneratedTexCoords[i]);
351
352 #ifdef STREAM_POLY_VERBOSE
353 printf ("mustGenerateTextures, MALLOCing newtc\n");
354 #endif
355
356 // some nodes will generate our tex coords for us, eg GeoElevationGrid
357 if (!r->GeneratedTexCoords[0]) {
358 newTexCoords[0] = MALLOC(float*, sizeof(float) * ntexdim[0] * r->ntri * 3); //always malloc at least one
359 for (k = 1; k < nmtexcoord; k++){
360 newTexCoords[k] = MALLOC(float*, sizeof(float) * ntexdim[k] * r->ntri * 3);
361 }
362 }
363
364 newcolors=0; /* only if we have colours*/
365
366 /* MALLOC required memory */
367 newcindex = MALLOC (GLuint *, sizeof (GLuint)*r->ntri*3);
368 newtcindex = MALLOC (GLuint *, sizeof (GLuint)*r->ntri*3);
369
370 newpoints = MALLOC (struct SFVec3f *, sizeof (struct SFVec3f)*r->ntri*3);
371
372 if(fogpoints)
373 newfog = MALLOC (float *, sizeof(float)*r->ntri*3);
374
375 if ((nnormals) || (r->normal)) {
376 newnorms = MALLOC (struct SFVec3f *, sizeof (struct SFVec3f)*r->ntri*3);
377 } else newnorms = 0;
378
379
380 /* if we have colours, make up a new structure for them to stream to, and also
381 copy pointers to ensure that we index through colorRGBAs properly. */
382 if (hasc) {
383 newcolors = MALLOC (struct SFColorRGBA *, sizeof (struct SFColorRGBA)*r->ntri*3);
384 oldColorsRGBA = (struct SFColorRGBA*) colors;
385 }
386
387 /* gather the min/max values for x,y, and z for default texture mapping, and Collisions */
388 for (j=0; j<3; j++) {
389 if (points) {
390 r->minVals[j] = points[r->cindex[0]].c[j];
391 r->maxVals[j] = points[r->cindex[0]].c[j];
392 } else {
393 if (r->actualCoord!=NULL) {
394 r->minVals[j] = r->actualCoord[3*r->cindex[0]+j];
395 r->maxVals[j] = r->actualCoord[3*r->cindex[0]+j];
396 }
397 }
398 }
399
400
401 for(i=0; i<r->ntri*3; i++) {
402 int ind = r->cindex[i];
403 for (j=0; j<3; j++) {
404 if(points) {
405 if (ind >= npoints) {
406 /* bounds checking... */
407 //r->minVals[j]=0.0f;
408 //r->maxVals[j]=0.0f;
409 //printf ("spv, warning, index %d >= npoints %d\n",ind,npoints);
410 } else {
411 if (r->minVals[j] > points[ind].c[j]) r->minVals[j] = points[ind].c[j];
412 if (r->maxVals[j] < points[ind].c[j]) r->maxVals[j] = points[ind].c[j];
413 }
414 } else if(r->actualCoord) {
415 if (r->minVals[j] > r->actualCoord[3*ind+j]) r->minVals[j] = r->actualCoord[3*ind+j];
416 if (r->maxVals[j] < r->actualCoord[3*ind+j]) r->maxVals[j] = r->actualCoord[3*ind+j];
417 } else {
418 r->minVals[j]=0.0f;
419 r->maxVals[j]=0.0f;
420 }
421 }
422 }
423
424 if (NO_TEXCOORD_NODE) {
425 defaultTextureMap(node, r);
426 }
427
428
429 /* now, lets go through the old, non-linear polyrep structure, and
430 put it in a stream format */
431
432 #ifdef STREAM_POLY_VERBOSE
433 printf ("before streaming for %p, extents %f %f, %f %f, %f %f\n",
434 node,
435 node->EXTENT_MAX_X,
436 node->EXTENT_MIN_X,
437 node->EXTENT_MAX_Y,
438 node->EXTENT_MIN_Y,
439 node->EXTENT_MAX_Z,
440 node->EXTENT_MIN_Z);
441 #endif
442
443
444 extent6f_clear(node->_extent);
445 for(i=0; i<r->ntri*3; i++) {
446 int nori = i;
447 int coli = i;
448 int ind = r->cindex[i];
449
450 /* new cindex, this should just be a 1.... ntri*3 linear string */
451 newcindex[i] = i;
452 newtcindex[i]=i;
453
454 #ifdef STREAM_POLY_VERBOSE
455 printf ("rp, i, ntri*3 %d %d\n",i,r->ntri*3);
456 #endif
457
458 /* get normals and colors, if any */
459 if(r->norindex) { nori = r->norindex[i];}
460 else nori = ind;
461
462 if(r->colindex) {
463 coli = r->colindex[i];
464 }
465 else coli = ind;
466
467 /* get texture coordinates, if any */
468 if (r->tcindex) {
469 newtcindex[i] = r->tcindex[i];
470 #ifdef STREAM_POLY_VERBOSE
471 printf ("have textures, and tcindex i %d tci %d\n",i,newtcindex[i]);
472 #endif
473 }
474 /* printf ("for index %d, tci is %d\n",i,newtcindex[i]); */
475
476 /* get the normals, if there are any */
477 if(nnormals) {
478 if(nori >= nnormals) {
479 /* bounds check normals here... */
480 nori=0;
481 }
482 #ifdef STREAM_POLY_VERBOSE
483 printf ("nnormals at %d , nori %d ",(int) &normals[nori].c,nori);
484 fwnorprint (normals[nori].c);
485 #endif
486
487 do_glNormal3fv(&newnorms[i], normals[nori].c);
488 } else if(r->normal) {
489 #ifdef STREAM_POLY_VERBOSE
490 printf ("r->normal nori %d ",nori);
491 fwnorprint(r->normal+3*nori);
492 #endif
493
494 do_glNormal3fv(&newnorms[i], r->normal+3*nori);
495 }
496
497 if(hasc) {
498 if(ncolors) {
499 /* ColorMaterial -> these set Material too */
500 /* bounds check colors[] here */
501 if (coli >= ncolors) {
502 /* printf ("bounds check for Colors! have %d want %d\n",ncolors-1,coli);*/
503 coli = 0;
504 }
505 #ifdef STREAM_POLY_VERBOSE
506 printf ("coloUr ncolors %d, coli %d",ncolors,coli);
507 fwnorprint(colors[coli].c);
508 printf ("\n");
509 #endif
510 if (isRGBA)
511 do_glColor4fv(&newcolors[i],oldColorsRGBA[coli].c,isRGBA);
512 else
513 do_glColor4fv(&newcolors[i],colors[coli].c,isRGBA);
514 } else if(r->color) {
515 #ifdef STREAM_POLY_VERBOSE
516 printf ("coloUr");
517 fwnorprint(r->color+3*coli);
518 printf ("\n");
519 #endif
520 if (isRGBA)
521 do_glColor4fv(&newcolors[i],r->color+4*coli,isRGBA);
522 else
523 do_glColor4fv(&newcolors[i],r->color+3*coli,isRGBA);
524 }
525 }
526
527 /* Coordinate points */
528 if(points) {
529 //printf ("... hav points, ind %d npoints %d\n",ind,npoints);
530 if (ind>=npoints) {
531 /* bounds checking */
532 newpoints[i].c[0] = 0.0f;
533 newpoints[i].c[1] = 0.0f;
534 newpoints[i].c[2] = 0.0f;
535 //printf ("spv, warning, index %d >= npoints %d\n",ind,npoints);
536 } else {
537 memcpy (&newpoints[i], &points[ind].c[0],sizeof (struct SFColor));
538 if(newfog) memcpy(&newfog[i],&fogpoints[ind],sizeof(float));
539 #ifdef STREAM_POLY_VERBOSE
540 printf("Render (points) #%d = [%.5f, %.5f, %.5f] from [%.5f, %.5f, %.5f]\n",i,
541 newpoints[i].c[0],newpoints[i].c[1],newpoints[i].c[2],
542 points[ind].c[0], points[ind].c[1],points[ind].c[2]);
543 #endif
544 }
545 } else if(r->actualCoord) {
546 memcpy (&newpoints[i].c[0], &r->actualCoord[3*ind], sizeof(struct SFColor));
547 #ifdef STREAM_POLY_VERBOSE
548 printf("Render (r->actualCoord) #%d = [%.5f, %.5f, %.5f]\n",i,
549 newpoints[i].c[0],newpoints[i].c[1],newpoints[i].c[2]);
550 #endif
551 } else {
552 #ifdef STREAM_POLY_VERBOSE
553 printf ("spv, no points and no coords, setting to 0,0,0\n");
554 #endif
555 newpoints[i].c[0] = 0.0f; newpoints[i].c[1]=0.0f;newpoints[i].c[2]=0.0f;
556 }
557
558 /* TextureCoordinates */
559
560 //printf ("textureCoordPoint %p\n",textureCoordPoint);
561
562 if (!r->GeneratedTexCoords[0]) {
563 for(k=0;k<(max(1,nmtexcoord));k++){ //always do the first one
564 if (textureCoordPoint[k] != NULL) {
565 int ndim, jj;
566 int j = newtcindex[i];
567 //struct SFVec2f me;
568 float *me;
569
570 jj = 0;
571 // bounds checking
572 j = min(j, textureCoordPoint[k]->n - 1);
573 /*
574 if (j>=(textureCoordPoint[k]->n)) {
575 //this warning eats frame rate in HAnim
576 static int once = 0;
577 if(!once){
578 ConsoleMessage ("stream_polyrep, have tcindex %d, tex coords %d, overflow",j,textureCoordPoint[k]->n);
579 once = 1;
580 }
581 //j= 0;
582 //jj = (j / textureCoordPoint[k]->n) +1;
583 jj = textureCoordPoint[k]->n / max(1,nmtexcoord);
584 j= j % textureCoordPoint[k]->n;
585 }
586 */
587 // textureCoordPoint is a pointer to struct Multi_Vec2f;
588 // struct Multi_Vec2f is struct Multi_Vec2f { int n; struct SFVec2f *p; };
589 // struct SFVec2f is struct SFVec2f { float c[2]; };
590
591 // get the 2 tex coords from here, and copy them over to newTexCoords
592 ndim = ntexdim[k];
593 me = (float*)textureCoordPoint[k]->p; //[j]; //lets hope struct SFVec2f is same layout as float[2]
594 if (me) {
595 me = &me[j * ndim];
596 if (jj) {
597 //experiment for when not enough texture coordinates
598 newTexCoords[k][i * ndim] = me[0] / (float)(jj);
599 newTexCoords[k][i * ndim + 1] = me[1] / (float)(jj);
600 }
601 else {
602 newTexCoords[k][i * ndim] = me[0];
603 newTexCoords[k][i * ndim + 1] = me[1];
604 }
605 if (ndim > 2)
606 newTexCoords[k][i * ndim + 2] = me[2]; //me.c[1];
607 if (ndim > 3)
608 newTexCoords[k][i * ndim + 3] = me[3]; //me.c[1];
609 }
610 } else if(k==0) {
611 /* default textures */
612 /* we want the S values to range from 0..1, and the
613 T values to range from 0...S/T */
614 int ndim;
615 ppStreamPoly p = (ppStreamPoly)gglobal()->StreamPoly.prv;
616 ndim = ntexdim[k];
617 newTexCoords[k][i*ndim] = (newpoints[i].c[p->Sindex] - p->minVals[p->Sindex])/p->Ssize;
618 newTexCoords[k][i*ndim+1] = (newpoints[i].c[p->Tindex] - p->minVals[p->Tindex])/p->Ssize;
619 if(ndim>2){
620 //problem doesn't seem to be a Rindex, lets hope we never get here?
621 newTexCoords[k][i*ndim+2] = (newpoints[i].c[p->Tindex] - p->minVals[p->Tindex])/p->Ssize;;
622 }
623 if(ndim>3)
624 newTexCoords[k][i*ndim+3] = 1.0f; //homogenous w
625
626 }
627 }
628 }
629
630 /* calculate maxextents */
631 /*
632 printf ("sp %u, looking at pts %f %f %f for %d\n",p,newpoints[i].c[0],
633 newpoints[i].c[1], newpoints[i].c[2],i);
634 */
635 if(0){
636 if (newpoints[i].c[0] > node->EXTENT_MAX_X) node->EXTENT_MAX_X = newpoints[i].c[0];
637 if (newpoints[i].c[0] < node->EXTENT_MIN_X) node->EXTENT_MIN_X = newpoints[i].c[0];
638 if (newpoints[i].c[1] > node->EXTENT_MAX_Y) node->EXTENT_MAX_Y = newpoints[i].c[1];
639 if (newpoints[i].c[1] < node->EXTENT_MIN_Y) node->EXTENT_MIN_Y = newpoints[i].c[1];
640 if (newpoints[i].c[2] > node->EXTENT_MAX_Z) node->EXTENT_MAX_Z = newpoints[i].c[2];
641 if (newpoints[i].c[2] < node->EXTENT_MIN_Z) node->EXTENT_MIN_Z = newpoints[i].c[2];
642 }else{
643 extent6f_union_vec3f(node->_extent,newpoints[i].c);
644 }
645 }
646 /* free the old, and make the new current. Just in case threading on a multiprocessor
647 machine comes walking through and expects to stream... */
648 FREE_IF_NZ(r->actualCoord);
649 r->actualCoord = (float *)newpoints;
650 FREE_IF_NZ(r->normal);
651 r->normal = (float *)newnorms;
652 FREE_IF_NZ(r->flat_normal);
653 r->oindex = r->cindex; //transfer cindex to oindex before copying newcindex to cindex, for skinning
654 r->cindex = NULL;
655 FREE_IF_NZ(r->cindex);
656 r->cindex = newcindex;
657 FREE_IF_NZ(r->actualFog);
658 r->actualFog = (float*)newfog;
659
660 //printf ("now, newTexCoords %p\n",newTexCoords);
661 //for (i=0; i<10; i++) printf ("rightpere, tc %d gt[i] %f\n",i,r->GeneratedTexCoords[0][i]);
662 /* did we have to generate tex coords? */
663 for(k=0;k<max(1,nmtexcoord);k++){
664 if (newTexCoords[k] != NULL) {
665 FREE_IF_NZ(r->GeneratedTexCoords[k]);
666 r->GeneratedTexCoords[k] = newTexCoords[k];
667 //printf("k=%d\n",k);
668 //for(int kk=0;kk<r->ntri*3;kk++){
669 // printf("%d %f %f\n",kk,r->GeneratedTexCoords[k][kk*2],r->GeneratedTexCoords[k][kk*2 +1]);
670 //}
671 }
672 }
673 r->ntcoord = nmtexcoord;
674 memcpy(r->ntexdim,ntexdim,4*sizeof(int));
675 memcpy(r->map, map, 4 * sizeof(char*));
676 FREE_IF_NZ(r->color);
677 FREE_IF_NZ(r->colindex);
678
679 if(temp_points) {
680 FREE_IF_NZ(points);
681 }
682
683 r->color = (float *)newcolors;
684
685 /* texture index */
686 FREE_IF_NZ(r->tcindex);
687 r->tcindex=newtcindex;
688
689 /* we dont require these indexes any more */
690 FREE_IF_NZ(r->norindex);
691
692 #ifdef STREAM_POLY_VERBOSE
693 printf ("end stream_polyrep - ntri %d\n\n",r->ntri);
694 #endif
695
696 /* finished streaming, tell the rendering thread that we can now display this one */
697 r->streamed=TRUE;
698
699 /* record the transparency, in case we need to re-do this field */
700 //r->transparency = thisTrans;
701 r->isRGBAcolorNode = isRGBA;
702
703 /* send the data to VBOs if required */
704 /* printf("stream polyrep, uploading vertices to VBO %u and %u\n",r->VBO_buffers[VERTEX_VBO], r->VBO_buffers[INDEX_VBO]); */
705 if (r->normal) {
706 if (r->VBO_buffers[NORMAL_VBO] == 0) glGenBuffers(1,&r->VBO_buffers[NORMAL_VBO]);
707 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,r->VBO_buffers[NORMAL_VBO]);
708 glBufferData(GL_ARRAY_BUFFER,r->ntri*sizeof(struct SFColor)*3,r->normal, GL_STATIC_DRAW);
709 //FREE_IF_NZ(r->normal);
710 }
711
712 if (r->color) {
713 if (r->VBO_buffers[COLOR_VBO] == 0) glGenBuffers(1,&r->VBO_buffers[COLOR_VBO]);
714 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,r->VBO_buffers[COLOR_VBO]);
715 glBufferData(GL_ARRAY_BUFFER,r->ntri*sizeof(struct SFColorRGBA)*3,r->color, GL_STATIC_DRAW);
716 // needed by recalculateColorField ... FREE_IF_NZ(r->color);
717 }
718 if (newfog) {
719 if (r->VBO_buffers[FOG_VBO] == 0) glGenBuffers(1,&r->VBO_buffers[FOG_VBO]);
720 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,r->VBO_buffers[FOG_VBO]);
721 glBufferData(GL_ARRAY_BUFFER,r->ntri*sizeof(float)*3,r->actualFog, GL_STATIC_DRAW);
722 }
723 if (r->oindex) {
724 //original coordinate indexes, still 3 per triangle, but index into original Coordinate.point.p
725 //used for humanoid skinning in shader fw_Cindex attribute
726 PRINT_GL_ERROR_IF_ANY("Stream OINDEX 0");
727 if (r->VBO_buffers[CINDEX_VBO] == 0) glGenBuffers(1, &r->VBO_buffers[CINDEX_VBO]);
728 PRINT_GL_ERROR_IF_ANY("Stream OINDEX 1");
729 //FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, r->VBO_buffers[CINDEX_VBO]);
730 glBindBuffer(GL_ARRAY_BUFFER, r->VBO_buffers[CINDEX_VBO]);
731 PRINT_GL_ERROR_IF_ANY("Stream OINDEX 2");
732 glBufferData(GL_ARRAY_BUFFER, r->ntri * sizeof(int) * 3, r->oindex, GL_STATIC_DRAW);
733 PRINT_GL_ERROR_IF_ANY("Stream OINDEX 3");
734 if (0) {
735 static int once = 0;
736 if (!once)
737 for (int j = 0; j < r->ntri; j++)
738 {
739 printf("[");
740 for (int k = 0; k < 3; k++)
741 printf("%d ", r->oindex[(3 * j) + k]);
742 printf("]");
743 }
744 once = 1;
745 }
746 }
747
748 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,r->VBO_buffers[VERTEX_VBO]);
749 glBufferData(GL_ARRAY_BUFFER,r->ntri*sizeof(struct SFColor)*3,r->actualCoord, GL_STATIC_DRAW);
750
751 FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER,r->VBO_buffers[INDEX_VBO]);
752
753 // OpenGL ES can use GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE for glDrawElements; force the indices to be this way.
754 if(0){
755 //surface triangle indices - dug9 aug 2016: H: we don't need/use these triangle indices
756 //because we do glDrawArrays(GL_TRIANGLES,,,) in Polyrep.c which doesn't use indices.
757 //(glDrawElements uses indices, used below for wireframe)
758 int i;
759 GLuint *to;
760 unsigned int *from;
761
762 r->tri_indices = MALLOC(GLuint *, sizeof(GLuint) * r->ntri*3);
763
764 to = r->tri_indices;
765 from = r->cindex;
766
767 for (i=0; i<r->ntri*3; i++) {
768 //printf ("and, index %d is %d\n",i,*from);
769 *to = (GLuint) *from; to++; from++;
770 }
771
772 glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof (GLuint)*r->ntri*3,r->tri_indices,GL_STATIC_DRAW); /* OpenGL-ES */
773 //FREE_IF_NZ(myindicies);
774 }
775 {
776 //wireframe lines - prepare in case someone does SHADINGSTYLE_WIRE
777 int i, i3, i6;
778 GLuint *lindex;
779 FREE_IF_NZ(r->wire_indices);
780 lindex = MALLOC(GLuint *, sizeof(GLuint) * r->ntri*3*2);
781
782 for(i=0;i<r->ntri;i++){
783 i3 = i*3;
784 i6 = i*6;
785 lindex[i6+0] = i3 + 0;
786 lindex[i6+1] = i3 + 1;
787 lindex[i6+2] = i3 + 1;
788 lindex[i6+3] = i3 + 2;
789 lindex[i6+4] = i3 + 2;
790 lindex[i6+5] = i3 + 0;
791 }
792 //we just save them, don't set them here.
793 r->wire_indices = lindex;
794 //then in Polyrep, when drawing on each frame, if we go into SHADINGSTYLE_WIRE then
795 // we swap in wire indices and call glDrawElements without coming back here
796 //glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof (GLushort)*r->ntri*3*2,r->wire_indices,GL_STATIC_DRAW); /* OpenGL-ES */
797 //FREE_IF_NZ(myindicies);
798 }
799 {
800 //prepare flat normals / face normals for SHADINGSTYLE_FLAT
801 int i9;
802 FREE_IF_NZ(r->flat_normal);
803 r->flat_normal = MALLOC(GLfloat*,r->ntri*sizeof(struct SFColor)*3);
804 for(i=0;i<r->ntri;i++){
805 float a[3],b[3],c[3],d[3], e[3], f[3], g[3];
806 i9 = i*9; //9 floats per triangle
807 memcpy(a,&r->actualCoord[i9 +0],sizeof(struct SFColor));
808 memcpy(b,&r->actualCoord[i9 +3],sizeof(struct SFColor));
809 memcpy(c,&r->actualCoord[i9 +6],sizeof(struct SFColor));
810 vecdif3f(d,b,a);
811 vecdif3f(e,c,a);
812 veccross3f(f,d,e);
813 vecnormalize3f(g,f);
814 memcpy(&r->flat_normal[i9 +0],g,sizeof(struct SFColor));
815 memcpy(&r->flat_normal[i9 +3],g,sizeof(struct SFColor));
816 memcpy(&r->flat_normal[i9 +6],g,sizeof(struct SFColor));
817 }
818 }
819 // Can we free this here, or do we need it later? FREE_IF_NZ(r->cindex);
820
821 for(k=0;k<max(1,nmtexcoord);k++){
822 if (r->GeneratedTexCoords[k]) {
823 if (r->VBO_buffers[TEXTURE_VBO0+k] == 0) glGenBuffers(1,&r->VBO_buffers[TEXTURE_VBO0+k]);
824 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,r->VBO_buffers[TEXTURE_VBO0+k]);
825 glBufferData(GL_ARRAY_BUFFER,sizeof (float)*r->ntexdim[k]*r->ntri*3,r->GeneratedTexCoords[k], GL_STATIC_DRAW);
826 //if(1) for(int kk=0;kk<r->ntri*3;kk++){
827 // printf("%f %f 0.0,\n",r->GeneratedTexCoords[0][kk*2],r->GeneratedTexCoords[0][kk*2 + 1]);
828 // if(kk % 50 == 0)
829 // printf("\n");
830 //}
831 /* finished with these - if we did not use it as a flag later, we could get rid of it */
832 //FREE_IF_NZ(r->GeneratedTexCoords);
833 }
834 }
835
836
837 #ifdef STREAM_POLY_VERBOSE
838 printf ("end spv for %p, extents %f %f, %f %f, %f %f\n",
839 node,
840 node->EXTENT_MAX_X,
841 node->EXTENT_MIN_X,
842 node->EXTENT_MAX_Y,
843 node->EXTENT_MIN_Y,
844 node->EXTENT_MAX_Z,
845 node->EXTENT_MIN_Z);
846 #endif
847
848}
849
850static void defaultTextureMap(struct X3D_Node *p, struct X3D_PolyRep * r) { //, struct SFVec3f *points, int npoints) {
851 ppStreamPoly psp = (ppStreamPoly)gglobal()->StreamPoly.prv;
852
853 /* variables used only in this routine */
854 GLfloat Tsize = 0.0f;
855 GLfloat Xsize = 0.0f;
856 GLfloat Ysize = 0.0f;
857 GLfloat Zsize = 0.0f;
858
859 /* initialize variables used in other routines in this file. */
860 psp->Sindex = 0; psp->Tindex = 0;
861 psp->Ssize = 0.0f;
862 psp->minVals[0]=r->minVals[0];
863 psp->minVals[1]=r->minVals[1];
864 psp->minVals[2]=r->minVals[2];
865
866 #ifdef STREAM_POLY_VERBOSE
867 printf ("have to gen default textures\n");
868 #endif
869
870 UNUSED(Tsize); // compiler warnings mitigation
871
872 if (p->_nodeType == NODE_IndexedFaceSet || p->_nodeType == NODE_ElevationGrid) {
873 /* find the S,T mapping. */
874 Xsize = r->maxVals[0]-psp->minVals[0];
875 Ysize = r->maxVals[1]-psp->minVals[1];
876 Zsize = r->maxVals[2]-psp->minVals[2];
877
878 /* printf ("defaultTextureMap, %f %f %f\n",Xsize,Ysize,Zsize); */
879
880 if ((Xsize >= Ysize) && (Xsize >= Zsize)) {
881 /* X size largest */
882 psp->Ssize = Xsize; psp->Sindex = 0;
883 if (Ysize >= Zsize) {
884 Tsize = Ysize; psp->Tindex = 1;
885 } else {
886 Tsize = Zsize; psp->Tindex = 2;
887 }
888 } else if ((Ysize >= Xsize) && (Ysize >= Zsize)) {
889 /* Y size largest */
890 psp->Ssize = Ysize; psp->Sindex = 1;
891 if (Xsize >= Zsize) {
892 Tsize = Xsize; psp->Tindex = 0;
893 } else {
894 Tsize = Zsize; psp->Tindex = 2;
895 }
896 } else {
897 /* Z is the largest */
898 psp->Ssize = Zsize; psp->Sindex = 2;
899 if (Xsize >= Ysize) {
900 Tsize = Xsize; psp->Tindex = 0;
901 } else {
902 Tsize = Ysize; psp->Tindex = 1;
903 }
904 }
905 }
906}