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