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