FreeWRL/FreeX3D  3.0.0
Component_Rendering.c
1 /*
2 
3 
4 X3D Rendering Component
5 
6 */
7 
8 
9 /****************************************************************************
10  This file is part of the FreeWRL/FreeX3D Distribution.
11 
12  Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
13 
14  FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
15  it under the terms of the GNU Lesser Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  FreeWRL/FreeX3D is distributed in the hope that it will be useful,
20  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  GNU General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
26 ****************************************************************************/
27 
28 
29 
30 #include <config.h>
31 #include <system.h>
32 #include <display.h>
33 #include <internal.h>
34 
35 #include <libFreeWRL.h>
36 
37 #include "../vrml_parser/Structs.h"
38 #include "../main/headers.h"
39 #include "../opengl/Frustum.h"
40 #include "../opengl/Material.h"
41 #include "../opengl/OpenGL_Utils.h"
42 #include "Component_Shape.h"
43 #include "../scenegraph/RenderFuncs.h"
44 #include "../scenegraph/Polyrep.h"
45 
46 #define FW_MAXCLIPPLANES 4
47 
48 typedef struct pComponent_Rendering{
49 
50  Stack *clipplane_stack;
51  float clipplanes[4*FW_MAXCLIPPLANES];
53 void *Component_Rendering_constructor(){
54  void *v = MALLOCV(sizeof(struct pComponent_Rendering));
55  memset(v,0,sizeof(struct pComponent_Rendering));
56  return v;
57 }
58 void Component_Rendering_init(struct tComponent_Rendering *t){
59  //public
60 
61  //private
62  t->prv = Component_Rendering_constructor();
63  {
65  p->clipplane_stack = newStack(usehit);
66  }
67 }
68 void Component_Rendering_clear(struct tComponent_Rendering *t){
70  deleteVector(struct X3D_Node*,p->clipplane_stack);
71 }
72 
73 
74 
75 /* find a bounding box that fits the coord structure. save it in the common-node area for extents.*/
76 static void findExtentInCoord (struct X3D_Node *node, int count, struct SFVec3f* coord) {
77  int i;
78 
79  INITIALIZE_EXTENT
80 
81  if (!coord) return;
82 
83  for (i=0; i<count; i++) {
84  if (coord->c[0] > node->EXTENT_MAX_X) node->EXTENT_MAX_X = coord->c[0];
85  if (coord->c[0] < node->EXTENT_MIN_X) node->EXTENT_MIN_X = coord->c[0];
86  if (coord->c[1] > node->EXTENT_MAX_Y) node->EXTENT_MAX_Y = coord->c[1];
87  if (coord->c[1] < node->EXTENT_MIN_Y) node->EXTENT_MIN_Y = coord->c[1];
88  if (coord->c[2] > node->EXTENT_MAX_Z) node->EXTENT_MAX_Z = coord->c[2];
89  if (coord->c[2] < node->EXTENT_MIN_Z) node->EXTENT_MIN_Z = coord->c[2];
90  coord++;
91  }
92  /* printf ("extents %f %f, %f %f, %f %f\n",node->EXTENT_MIN_X, node->EXTENT_MAX_X,
93  node->EXTENT_MIN_Y, node->EXTENT_MAX_Y, node->EXTENT_MIN_Z, node->EXTENT_MAX_Z); */
94 }
95 
96 void render_IndexedTriangleFanSet (struct X3D_IndexedTriangleFanSet *node) {
97  COMPILE_POLY_IF_REQUIRED(node->coord, node->fogCoord, node->color, node->normal, node->texCoord)
98  CULL_FACE(node->solid)
99  render_polyrep(node);
100 }
101 
102 void render_IndexedTriangleSet (struct X3D_IndexedTriangleSet *node) {
103  COMPILE_POLY_IF_REQUIRED(node->coord, node->fogCoord, node->color, node->normal, node->texCoord)
104  CULL_FACE(node->solid)
105  render_polyrep(node);
106 
107 }
108 
109 void render_IndexedTriangleStripSet (struct X3D_IndexedTriangleStripSet *node) {
110  COMPILE_POLY_IF_REQUIRED( node->coord, node->fogCoord, node->color, node->normal, NULL)
111  CULL_FACE(node->solid)
112  render_polyrep(node);
113 }
114 
115 void render_TriangleFanSet (struct X3D_TriangleFanSet *node) {
116  COMPILE_POLY_IF_REQUIRED (node->coord, node->fogCoord, node->color, node->normal, node->texCoord)
117  CULL_FACE(node->solid)
118  render_polyrep(node);
119 }
120 
121 void render_TriangleStripSet (struct X3D_TriangleStripSet *node) {
122  COMPILE_POLY_IF_REQUIRED(node->coord, node->fogCoord, node->color, node->normal, node->texCoord)
123  CULL_FACE(node->solid)
124  render_polyrep(node);
125 }
126 
127 void render_TriangleSet (struct X3D_TriangleSet *node) {
128  COMPILE_POLY_IF_REQUIRED(node->coord, node->fogCoord, node->color, node->normal, node->texCoord)
129  CULL_FACE(node->solid)
130  render_polyrep(node);
131 }
132 
133 
134 
135 void compile_IndexedLineSet (struct X3D_IndexedLineSet *node) {
136  int i; /* temporary */
137  struct SFVec3f *points;
138  struct SFVec3f *newpoints;
139  struct SFVec3f *oldpoint;
140  struct SFColorRGBA *newcolors;
141  struct SFColorRGBA *oldcolor;
142  int npoints;
143  int maxCoordFound; /* for bounds checking */
144  struct X3D_Color *cc;
145  int nSegments; /* how many individual lines in this shape */
146  int curSeg; /* for colours, !cpv, this is the color index */
147  int nVertices; /* how many vertices in the streamed set */
148  int segLength; /* temporary */
149  ushort *vertCountPtr; /* temporary, for vertexCount filling */
150  ushort **indxStartPtr; /* temporary, for creating pointer to index arr */
151 
152  ushort * pt;
153  int vtc; /* temp counter - "vertex count" */
154  int curcolor; /* temp for colorIndexing. */
155  int * colorIndInt; /* used for streaming colors */
156  ushort * colorIndShort; /* used for streaming colors */
157 
158  /* believe it or not - material emissiveColor can affect us... */
159  GLfloat defcolorRGBA[] = {1.0f, 1.0f, 1.0f,1.0f};
160 
161  /* we either use the (sizeof (int)) indices passed in from user, or calculated ushort one */
162  colorIndInt = NULL;
163  colorIndShort = NULL;
164 
165  MARK_NODE_COMPILED
166  nSegments = 0;
167  node->__segCount = 0;
168 
169  /* ok, what we do is this. Although this is Indexed, colours and vertices can have
170  different indexes; so we make them all the same. To do this, we create another
171  index (really simple one - element x contains x...) that we send to the OpenGL
172  calls.
173 
174  So first, we find out the maximum coordinate requested in the IndexedLineSet,
175  AND, we find out how many line segments there are.
176  */
177 
178  if (node->coord) {
179  struct Multi_Vec3f *dtmp;
180  dtmp = getCoordinate (node->coord, "IndexedLineSet");
181  npoints = dtmp->n;
182  points = dtmp->p;
183 
184  /* find the extents */
185  findExtentInCoord(X3D_NODE(node), npoints, points);
186  } else {
187  return; /* no coordinates - nothing to do */
188  }
189 
190  if (node->coordIndex.n == 0) return; /* no coord indexes - nothing to do */
191 
192  /* sanity check that we have enough coordinates */
193  maxCoordFound = -1000;
194  nSegments = 1;
195  nVertices = 0;
196  for (i=0; i<node->coordIndex.n; i++) {
197  /* make sure that the coordIndex is greater than -1 */
198  if (node->coordIndex.p[i] < -1) {
199  ConsoleMessage ("IndexedLineSet - coordIndex less than 0 at %d\n",i);
200  return;
201  }
202 
203  /* count segments; dont bother if the very last number is -1 */
204  if (node->coordIndex.p[i] == -1) {
205  if (i!=((node->coordIndex.n)-1)) nSegments++;
206  } else nVertices++;
207 
208  /* try to find the highest coordinate index for bounds checking */
209  if (node->coordIndex.p[i] > maxCoordFound) maxCoordFound = node->coordIndex.p[i];
210  }
211  if (maxCoordFound > npoints) {
212  //JAS - cheat - remove the BoundingBox for root node by simply making the coordinate element count 0,
213  //JAS - but if we do that, we get this console message.
214  //JAS ConsoleMessage ("IndexedLineSet - not enough coordinates - coordindex contains higher index\n");
215  return;
216  }
217 
218  /* so, at this step, we know how many line segments "nSegments" we require (starting at 0)
219  and, what the maximum coordinate is. So, lets create the new index...
220  create the index for the arrays. Really simple... Used to index
221  into the coords, so, eg, __vertArr is [0,1,2], which means use
222  coordinates 0, 1, and 2 */
223  FREE_IF_NZ (node->__vertArr);
224  node->__vertArr = MALLOC (ushort *, sizeof(ushort)*(nVertices+1));
225  pt = (ushort *)node->__vertArr;
226 
227  for (vtc = 0; vtc < nVertices; vtc++) {
228  *pt=vtc; pt++; /* ie, index n contains the number n */
229  }
230 
231 
232  /* now, lets go through and; 1) copy old vertices into new vertex array; and
233  2) create an array of indexes into "__vertArr" for sending to the GL call */
234 
235 
236  FREE_IF_NZ (node->__vertIndx);
237  node->__vertIndx = MALLOC (ushort **,sizeof(ushort*)*(nSegments));
238 
239  FREE_IF_NZ (node->__vertices);
240  node->__vertices = MALLOC (struct SFVec3f *, sizeof(struct SFVec3f)*(nVertices+1));
241 
242  FREE_IF_NZ (node->__vertexCount);
243  node->__vertexCount = MALLOC (ushort *,sizeof(ushort)*(nSegments));
244 
245 
246  indxStartPtr = (ushort **)node->__vertIndx;
247  newpoints = node->__vertices;
248  vertCountPtr = (ushort *) node->__vertexCount;
249 
250  pt = (ushort *)node->__vertArr;
251 
252  vtc=0;
253  segLength=0;
254  *indxStartPtr = pt; /* first segment starts off at index zero */
255 
256  indxStartPtr++;
257 
258  for (i=0; i<node->coordIndex.n; i++) {
259  /* count segments; dont bother if the very last number is -1 */
260  if (node->coordIndex.p[i] == -1) {
261  if (i!=((node->coordIndex.n)-1)) {
262  /* new segment */
263  *indxStartPtr = pt;
264  indxStartPtr++;
265 
266  /* record the old segment length */
267  *vertCountPtr = segLength;
268  segLength=0;
269  vertCountPtr ++;
270  }
271  } else {
272  /* new vertex */
273  oldpoint = &points[node->coordIndex.p[i]];
274  memcpy (newpoints, oldpoint,sizeof(struct SFColor));
275  newpoints ++;
276  segLength ++;
277  pt ++;
278  }
279  }
280 
281  /* do we have to worry about colours? */
282  /* sanity check the colors, if they exist */
283  if (node->color) {
284  /* we resort the color nodes so that we have an RGBA color node per vertex */
285  FREE_IF_NZ (node->__xcolours);
286  node->__xcolours = MALLOC (struct SFColorRGBA *, sizeof(struct SFColorRGBA)*(nVertices+1));
287  newcolors = (struct SFColorRGBA *) node->__xcolours;
288  POSSIBLE_PROTO_EXPANSION(struct X3D_Color *, node->color,cc)
289  /* cc = (struct X3D_Color *) node->color; */
290  if(cc)
291  if ((cc->_nodeType != NODE_Color) && (cc->_nodeType != NODE_ColorRGBA)) {
292  ConsoleMessage ("make_IndexedLineSet, color node, expected %d got %d\n", NODE_Color, cc->_nodeType);
293  return;
294  }
295 
296  /* 4 choices here - we have colorPerVertex, and, possibly, a ColorIndex */
297 
298  if (node->colorPerVertex) {
299  /* assume for now that we are using the coordIndex for colour selection */
300  colorIndInt = node->coordIndex.p;
301  /* so, we have a color per line segment. Lets check this stuff... */
302  if ((node->colorIndex.n)>0) {
303  if ((node->colorIndex.n) < (node->coordIndex.n)) {
304  ConsoleMessage ("IndexedLineSet - expect more colorIndexes to match coords\n");
305  return;
306  }
307  colorIndInt = node->colorIndex.p; /* use ColorIndex */
308  } else {
309  colorIndShort = node->__vertArr;
310  }
311  } else {
312 
313  /* so, we have a color per line segment. Lets check this stuff... */
314  if ((node->colorIndex.n)>0) {
315  if ((node->colorIndex.n) < (nSegments)) {
316  ConsoleMessage ("IndexedLineSet - expect more colorIndexes to match coords\n");
317  return;
318  }
319  colorIndInt = node->colorIndex.p; /* use ColorIndex */
320  } else {
321  /* we are using the simple index for colour selection */
322  colorIndShort = node->__vertArr;
323  }
324  }
325 
326 
327  /* go and match colors with vertices */
328  curSeg = 0;
329  for (i=0; i<node->coordIndex.n; i++) {
330  if (node->coordIndex.p[i] != -1) {
331  /* have a vertex, match colour */
332  if (node->colorPerVertex) {
333  if (colorIndInt != NULL)
334  curcolor = colorIndInt[i];
335  else
336  curcolor = colorIndShort[i];
337  } else {
338  if (colorIndInt != NULL)
339  curcolor = colorIndInt[curSeg];
340  else
341  curcolor = colorIndShort[curSeg];
342  }
343  //ConsoleMessage ("curSeg %d, i %d, node->coordIndex.p %d curcolor %d\n",curSeg,i,node->coordIndex.p[i], curcolor);
344  if ((curcolor < 0) || (curcolor >= cc->color.n)) {
345  ConsoleMessage ("IndexedLineSet, colorIndex %d (for vertex %d or segment %d) out of range (0..%d)\n",
346  curcolor, i, curSeg, cc->color.n);
347  return;
348  }
349 
350  oldcolor = (struct SFColorRGBA *) &(cc->color.p[curcolor]);
351 
352  /* copy the correct color over for this vertex */
353  if (cc->_nodeType == NODE_Color) {
354  memcpy (newcolors, defcolorRGBA, sizeof (defcolorRGBA));
355  memcpy (newcolors, oldcolor,sizeof(struct SFColor));
356  } else {
357  memcpy (newcolors, oldcolor,sizeof(struct SFColorRGBA));
358  }
359  //printf ("colout selected %f %f %f %f\n",newcolors->c[0],newcolors->c[1],newcolors->c[2],newcolors->c[3]);
360  newcolors ++;
361  } else {
362  curSeg++;
363  }
364  }
365  }
366 
367  /* finished worrying about colours */
368 
369  /* finish this for loop off... */
370  *vertCountPtr = segLength;
371  node->__segCount = nSegments; /* we passed, so we can render */
372 }
373 
374 void render_IndexedLineSet (struct X3D_IndexedLineSet *node) {
375  ushort **indxStartPtr;
376  ushort *count;
377  int i;
378  ttglobal tg = gglobal();
379 
380  LIGHTING_OFF
381  DISABLE_CULL_FACE
382 
383  COMPILE_IF_REQUIRED
384 
385  setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X, node->EXTENT_MAX_Y,
386  node->EXTENT_MIN_Y, node->EXTENT_MAX_Z, node->EXTENT_MIN_Z,
387  X3D_NODE(node));
388 
389 
390  /* If we have segments... */
391  if (node->__segCount > 0) {
392  FW_GL_VERTEX_POINTER (3,GL_FLOAT,0,node->__vertices);
393 
394  if (node->__xcolours) {
395  FW_GL_COLOR_POINTER (4,GL_FLOAT,0,node->__xcolours);
396  }
397 
398  indxStartPtr = (ushort **)node->__vertIndx;
399  count = node->__vertexCount;
400 
401  for (i=0; i<node->__segCount; i++) {
402  // draw. Note the casting of the last param - it is ok, because we tell that
403  // we are sending in ushorts; it gets around a compiler warning.
404  sendElementsToGPU(GL_LINE_STRIP,count[i],indxStartPtr[i]);
405  }
406  }
407 }
408 
409 void compile_PointSet (struct X3D_PointSet *node) {
410  struct SFColor *colors=0; int ncolors=0;
411  struct X3D_Color *cc;
412 
413  if (node->_pointsVBO == 0) {
414  glGenBuffers(1,(GLuint *) &node->_pointsVBO);
415  }
416 
417  /* do nothing, except get the extents here */
418  MARK_NODE_COMPILED
419 
420  node->_npoints = 0;
421 
422  if (node->coord) {
423  struct Multi_Vec3f *dtmp;
424  dtmp = getCoordinate (node->coord, "PointSet");
425 
426  /* find the extents */
427  findExtentInCoord(X3D_NODE(node), dtmp->n, dtmp->p);
428 
429  if (dtmp->n == 0) return;
430  FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, (GLuint) node->_pointsVBO);
431  glBufferData(GL_ARRAY_BUFFER, sizeof(struct SFVec3f)*dtmp->n, dtmp->p, GL_STATIC_DRAW);
432  FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,0);
433  node->_npoints = dtmp->n;
434  }
435 
436  if (node->color) {
437  POSSIBLE_PROTO_EXPANSION(struct X3D_Color *, node->color,cc)
438  if(cc){
439  if ((cc->_nodeType != NODE_Color) && (cc->_nodeType != NODE_ColorRGBA)) {
440  ConsoleMessage ("make_PointSet, expected %d got %d\n", NODE_Color, cc->_nodeType);
441  } else {
442  ncolors = cc->color.n;
443  colors = cc->color.p;
444  }
445  }
446 
447 
448  if(ncolors && ncolors < node->_npoints) {
449  ConsoleMessage ("PointSet has less colors than points - removing color\n");
450  ncolors = 0;
451  } else {
452  if (node->_coloursVBO == 0) {
453  glGenBuffers(1,(GLuint *)&node->_coloursVBO);
454  }
455 
456  /* RGB or RGBA? */
457  FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, (GLuint) node->_coloursVBO);
458  if (cc->_nodeType == NODE_Color) {
459  glBufferData(GL_ARRAY_BUFFER, sizeof(struct SFColor)*ncolors, colors, GL_STATIC_DRAW);
460  node->_colourSize = 3;
461  } else {
462  glBufferData(GL_ARRAY_BUFFER, sizeof(struct SFColorRGBA)*ncolors, colors, GL_STATIC_DRAW);
463  node->_colourSize = 4;
464  }
465  FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,0);
466  }
467  }
468 }
469 
470 
471 void render_PointSet (struct X3D_PointSet *node) {
472  ttglobal tg = gglobal();
473  COMPILE_IF_REQUIRED
474 
475  setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X, node->EXTENT_MAX_Y,
476  node->EXTENT_MIN_Y, node->EXTENT_MAX_Z, node->EXTENT_MIN_Z,
477  X3D_NODE(node));
478 
479  LIGHTING_OFF
480  DISABLE_CULL_FACE
481 
482  if (node->_pointsVBO == 0) return;
483 
484  FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, node->_pointsVBO);
485  FW_GL_VERTEX_POINTER(3,GL_FLOAT,0,0);
486 
487  // do we have colours?
488  if (node->_coloursVBO != 0) {
489  FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, node->_coloursVBO);
490  FW_GL_COLOR_POINTER(node->_colourSize,GL_FLOAT,0,0);
491  }
492  //printf ("ps is %d, vbo %d\n",node->_npoints, node->_pointsVBO);
493 
494  sendArraysToGPU(GL_POINTS,0,node->_npoints);
495 }
496 
497 void render_LineSet (struct X3D_LineSet *node) {
498 
499  struct X3D_Color *cc;
500  GLushort **indices;
501  GLsizei *count;
502  int i;
503  struct Multi_Vec3f* points;
504  ttglobal tg = gglobal();
505 
506  LIGHTING_OFF
507  DISABLE_CULL_FACE
508 
509  COMPILE_IF_REQUIRED
510 
511  setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X, node->EXTENT_MAX_Y,
512  node->EXTENT_MIN_Y, node->EXTENT_MAX_Z, node->EXTENT_MIN_Z,
513  X3D_NODE(node));
514 
515  /* now, actually draw array */
516  if (node->__segCount > 0) {
517  if (node->color) {
518  cc = (struct X3D_Color *) node->color;
519  /* is this a Color or ColorRGBA color node? */
520  if (cc->_nodeType == NODE_Color) {
521  FW_GL_COLOR_POINTER (3,GL_FLOAT,0,(float *)cc->color.p);
522  } else {
523  FW_GL_COLOR_POINTER (4,GL_FLOAT,0,(float *)cc->color.p);
524  }
525  }
526  points = getCoordinate(node->coord, "LineSet");
527 
528  FW_GL_VERTEX_POINTER (3,GL_FLOAT,0,(float *)points->p);
529 
530  indices = (ushort **)node->__vertIndx;
531  /* note the cast below - casting an int* to a GLsizei* seems to be ok on 32 and 64 bit systems */
532  count = (GLsizei*) node->vertexCount.p;
533 
534  for (i=0; i<node->__segCount; i++) {
535  /*
536  printf ("rendering segment %d of %d, count %d, have starting index of %hu\n",i,node->__segCount, count[i], *indices[i]);
537  {int j; ushort *pt = indices[i];
538  for (j=0; j<count[i]; j++) {
539  printf ("line segment %d, index %hu\n",i,*pt);
540  pt++;
541  }
542  }
543  */
544  sendElementsToGPU(GL_LINE_STRIP,count[i],indices[i]);
545  }
546  }
547 }
548 
549 
550 void compile_LineSet (struct X3D_LineSet *node) {
551  int vtc; /* which vertexCount[] we should be using for this line segment */
552  int c; /* temp variable */
553  struct SFVec3f *coord=0; int ncoord;
554  //struct SFColor *color=0;
555  int ncolor=0;
556  int *vertexC; int nvertexc;
557  int totVertexRequired;
558 
559  struct X3D_Color *cc;
560  GLushort *pt;
561  ushort **vpt;
562 
563  MARK_NODE_COMPILED
564  node->__segCount = 0; /* assume this for now */
565 
566 
567  nvertexc = (node->vertexCount).n; vertexC = (node->vertexCount).p;
568  if (nvertexc==0) return;
569  totVertexRequired = 0;
570 
571  //printf ("compile_LineSet, nvertexc %d\n",nvertexc);
572 
573 
574  /* sanity check vertex counts */
575  for (c=0; c<nvertexc; c++) {
576  totVertexRequired += vertexC[c];
577  if (vertexC[c]<2) {
578  ConsoleMessage ("make_LineSet, we have a vertexCount of %d, must be >=2,\n",vertexC[c]);
579  return;
580  }
581  }
582 
583  if (node->coord) {
584  struct Multi_Vec3f *dtmp;
585  dtmp = getCoordinate (node->coord, "IndexedLineSet");
586  ncoord = dtmp->n;
587  coord = dtmp->p;
588 
589  /* find the extents */
590  findExtentInCoord(X3D_NODE(node), ncoord, coord);
591  } else {
592  return; /* no coordinates - nothing to do */
593  }
594 
595  /* check that we have enough vertexes */
596  if (totVertexRequired > ncoord) {
597  ConsoleMessage ("make_LineSet, not enough points for vertexCount (vertices:%d points:%d)\n",
598  totVertexRequired, ncoord);
599  return;
600  }
601 
602  if (node->color) {
603  /* cc = (struct X3D_Color *) node->color; */
604  POSSIBLE_PROTO_EXPANSION(struct X3D_Color *, node->color,cc)
605  if(cc){
606  if ((cc->_nodeType != NODE_Color) && (cc->_nodeType != NODE_ColorRGBA)) {
607  ConsoleMessage ("make_LineSet, expected %d got %d\n", NODE_Color, cc->_nodeType);
608  } else {
609  ncolor = cc->color.n;
610  //color = cc->color.p;
611  }
612  }
613  /* check that we have enough verticies for the Colors */
614  if (totVertexRequired > ncolor) {
615  ConsoleMessage ("make_LineSet, not enough colors for vertexCount (vertices:%d colors:%d)\n",
616  totVertexRequired, ncolor);
617  return;
618  }
619  }
620 
621  /* create the index for the arrays. Really simple... Used to index
622  into the coords, so, eg, __vertArr is [0,1,2], which means use
623  coordinates 0, 1, and 2 */
624  FREE_IF_NZ (node->__vertArr);
625  node->__vertArr = MALLOC (GLuint *, sizeof(GLuint)*(ncoord));
626  pt = (GLushort *)node->__vertArr;
627  for (vtc = 0; vtc < ncoord; vtc++) {
628  *pt=vtc; pt++; /* ie, index n contains the number n */
629  }
630 
631  /* create the index for each line segment. What happens here is
632  that we create an array of pointers; each pointer points into
633  the __vertArr array - this gives a starting index for each line
634  segment The LENGTH of each segment (good question) comes from the
635  vertexCount parameter of the LineSet node */
636  FREE_IF_NZ (node->__vertIndx);
637  node->__vertIndx = MALLOC (ushort **, sizeof(ushort*)*(nvertexc));
638  c = 0;
639  pt = (GLushort *)node->__vertArr;
640  vpt = (ushort**) node->__vertIndx;
641  for (vtc=0; vtc<nvertexc; vtc++) {
642  //printf ("in position %d of __vertIndx, we have put pointer to %u\n",vtc,*pt);
643  vpt[vtc] = (ushort*) pt;
644  pt += vertexC[vtc];
645  }
646 
647  /* if we made it this far, we are ok tell the rendering engine that we are ok */
648  node->__segCount = nvertexc;
649 }
650 
651 /* ClipPlane
652  http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/rendering.html#ClipPlanes
653  http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/rendering.html#ClipPlane
654  GLES2 supports only frustum clipplane. For user clipplanes:
655  https://www.khronos.org/registry/gles/specs/2.0/es_cm_spec_2.0.25.pdf
656  "Userclipping planes can be emulated by dot product clipping plane and vertex, and threshold result in shader"
657  http://mrkaktus.org/opengl-clip-planes-explained/
658  - shows different gl versions and different support technique / mechanism, desktop different than ES2 different than ES3
659  A few links here to clipping in shader es 2:
660  http://stackoverflow.com/questions/7408855/clipping-planes-in-opengl-es-2-0
661  https://www.opengl.org/discussion_boards/showthread.php/171914-How-to-activate-clip-planes-via-shader
662 
663  Implementation Suggestions:
664  A. render_hier plubming
665  11.2.4.4 > scoping of clipplanes >
666  - their transform siblings are affected and children below
667  - (dug9: maybe it could/should have been a grouping node, with its own children, like collision?)
668  - to implement, you would use a stack, and push going down, pop coming back
669  - need to flag parent like other sibling-affectors - see OpenGL_UTils.c VF_Sensitive
670  - in render_node(node) on render_geom pass (doesn't make sense on any other pass?)
671  -on prep-side of children, test for VF_ClipPlane on parent, go through children to find ClipPlane, push clipplane
672  if node & VF_ClipPlane
673  ifound = push_child_clipplane(node);
674  if( ifound) pushed_clipplane = TRUE;
675  -on fin side of children, if pushed_clipplane pop_child_clipplane
676  B. shader plumbing
677  https://www.opengl.org/discussion_boards/showthread.php/171914-How-to-activate-clip-planes-via-shader
678  in shader:
679  uniform vec4 ClipPlane[MaxClipPlanes];
680  ...
681  for ( int i=0; i<MaxClipPlanes; i++ )
682  {
683  gl_ClipDistance[i] = dot( ClipPlane[i], vec4(MCvertex,1.0));
684  }
685 */
686 float *getTransformedClipPlanes(){
687  #define tactic_one_shot 1
688  #define tactic_point_plus_normal 2
689  int i,nsend, tactic;
690  double modelviewmatrix[16], meinv[16], u2me[16], me2u[16], me2ut[16], u2met[16], *M, *MIT;
691  ppComponent_Rendering p = (ppComponent_Rendering)gglobal()->Component_Rendering.prv;
692 
693  nsend = min(FW_MAXCLIPPLANES,vectorSize(p->clipplane_stack));
694  //Q. how transform a plane by a matrix?
695  //option 1: 4x4 * 4x1
696  //https://www.opengl.org/discussion_boards/showthread.php/159564-Clever-way-to-transform-plane-by-matrix
697  //tactic = tactic_one_shot; //works
698  //option 2: convert abcd plane into normal + 3d point, transform point and normal, then convert back to abcd
699  //http://stackoverflow.com/questions/7685495/transforming-a-3d-plane-by-4x4-matrix
700  tactic = tactic_point_plus_normal; //works
701  FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, modelviewmatrix);
702  matinverseAFFINE(meinv,modelviewmatrix);
703 
704  for(i=0;i<nsend;i++){
705  //we take from the top-most end of the stack, in case more than MAX, using vectorget
706  int j;
707  struct X3D_ClipPlane *cplane;
708  double dplane[4],dplane2[4];
709  usehit uhit;
710  uhit = vector_get(usehit,p->clipplane_stack,i);
711  cplane = (struct X3D_ClipPlane *)uhit.node;
712  matmultiplyAFFINE(u2me,uhit.mvm,meinv);
713  mattranspose(u2met,u2me);
714  matinverseAFFINE(me2u,u2me);
715  mattranspose(me2ut,me2u);
716  M = u2me; //matrix, for transforming point
717  MIT = me2ut; //matrix inverse transpose, for transforming normal
718 
719  for(j=0;j<4;j++) dplane[j] = cplane->plane.c[j]; //float to double
720  if(tactic == tactic_one_shot){
721  //works
722  transformFULL4d(dplane2,dplane,MIT);
723  }
724  else
725  {
726  //tactic_point_plus_normal - works
727  //vector4 O = (xyz * d, 1)
728  double O4[4], N4[4], d;
729  vecscaled(O4,dplane,-dplane[3]);
730  O4[3] = 1.0;
731  //vector4 N = (xyz, 0)
732  veccopyd(N4,dplane);
733  N4[3] = 0.0;
734  //O = M * O
735  transformAFFINEd(O4,O4,M);
736  //N = transpose(invert(M)) * N
737  transformAFFINEd(N4,N4,MIT);
738  //xyz = N.xyz
739  veccopyd(dplane2,N4);
740  //d = dot(O.xyz, N.xyz)
741  d = vecdotd(O4,N4);
742  dplane2[3] = -d;
743  }
744  for(j=0;j<4;j++) p->clipplanes[i*4 + j] = (float) dplane2[j]; //double to float
745  }
746  return p->clipplanes;
747 }
748 int getClipPlaneCount(){
749  int nsend;
750  ppComponent_Rendering p = (ppComponent_Rendering)gglobal()->Component_Rendering.prv;
751  nsend = min(FW_MAXCLIPPLANES,vectorSize(p->clipplane_stack));
752  return nsend;
753 }
754 void pushShaderFlags(shaderflagsstruct flags);
755 void popShaderFlags();
756 
757 void sib_prep_ClipPlane(struct X3D_Node *parent, struct X3D_Node *sibAffector){
758  //search for child clipplane
759  //if found and enabled
760  if(sibAffector && sibAffector->_nodeType == NODE_ClipPlane){
761  // push on stack like push_sensor()
762  struct X3D_ClipPlane * cplane = (struct X3D_ClipPlane*)sibAffector;
763  if(cplane->enabled == TRUE){
764  //unsigned int shaderflags;
765  shaderflagsstruct shaderflags;
766  double modelviewmatrix[16];
767  usehit uhit;
768  ppComponent_Rendering p = (ppComponent_Rendering)gglobal()->Component_Rendering.prv;
769 
770  shaderflags = getShaderFlags();
771  shaderflags.base |= CLIPPLANE_SHADER;
772  pushShaderFlags(shaderflags);
773 
774  //http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/rendering.html#ClipPlanes
775  //we'll snapshot the modelview matrix and push with clipplane node onto stack,
776  //for use when applying in leaf shape node
777  uhit.node = X3D_NODE(cplane); //x3dnode clipplane
778  FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, modelviewmatrix);
779  memcpy(uhit.mvm,modelviewmatrix,16*sizeof(double)); //deep copy
780  stack_push(usehit,p->clipplane_stack,uhit); //fat elements do another deep copy
781 
782  //jplane = vectorSize(p->clipplane_stack) -1;
783  //if(jplane < FW_MAXCLIPPLANES){
784  // memcpy(&p->clipplanes[jplane*4],cplane->plane.c,4*sizeof(float));
785  //}
786 
787  // somehow add to end of list of clipplanes available to shader (but how precisely?)
788  // https://www.opengl.org/discussion_boards/showthread.php/171914-How-to-activate-clip-planes-via-shader
789  // m_pProgram->SetUniform("ClipPlane[0]", vect, 4, 1);
790  // //except construct the name string: k = clipplanestac.n-1; "ClipPlane[%1d]",k
791  // glEnable(GL_CLIP_DISTANCE0); //except DISTANCEk ?
792  // might need: to set a flag indicating which shader to use?
793 
794  }
795  }
796 }
797 void sib_fin_ClipPlane(struct X3D_Node *parent, struct X3D_Node *sibAffector){
798  //pop clipplane
799  if(sibAffector && sibAffector->_nodeType == NODE_ClipPlane){
800  struct X3D_ClipPlane * cplane = (struct X3D_ClipPlane*)sibAffector;
801  if(cplane->enabled == TRUE){
802  ppComponent_Rendering p = (ppComponent_Rendering)gglobal()->Component_Rendering.prv;
803  stack_pop(usehit,p->clipplane_stack);
804  popShaderFlags();
805  }
806  }
807 }
Definition: Vector.h:36