FreeWRL / FreeX3D 4.3.0
Component_Rendering.c
1/*
2
3
4X3D 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
48typedef struct pComponent_Rendering{
49
50 Stack *clipplane_stack;
51 float clipplanes[4*FW_MAXCLIPPLANES];
53void *Component_Rendering_constructor(){
54 void *v = MALLOCV(sizeof(struct pComponent_Rendering));
55 memset(v,0,sizeof(struct pComponent_Rendering));
56 return v;
57}
58void 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}
68void 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.*/
76static 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
96void 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
102void 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
109void 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
115void 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
121void 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
127void 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
135void 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
374void 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
409void 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
471void 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
497void 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
550void 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*/
686float *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}
748int 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}
754void pushShaderFlags(shaderflagsstruct flags);
755void popShaderFlags();
756
757void 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}
797void 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}