FreeWRL/FreeX3D  3.0.0
Component_Geometry2D.c
1 /*
2 
3 
4 X3D Geometry2D 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 
40 #include "Collision.h"
41 #include "LinearAlgebra.h"
42 #include "../opengl/Frustum.h"
43 #include "../opengl/Material.h"
44 #include "Component_Geometry3D.h"
45 #include "../opengl/OpenGL_Utils.h"
46 #include "../opengl/Textures.h"
47 
48 #include "Component_Shape.h"
49 #include "../scenegraph/RenderFuncs.h"
50 
51 #include <float.h>
52 #if defined(_MSC_VER) && _MSC_VER < 1500
53 #define cosf cos
54 #define sinf sin
55 #endif
56 #define SEGMENTS_PER_CIRCLE 36
57 #define PIE 10
58 #define CHORD 20
59 #define NONE 30
60 
61 static void *createLines (float start, float end, float radius, int closed, int *size,float *_extent);
62 
63 #define COMPILE_AND_GET_BOUNDS(myType,myField) \
64 void compile_##myType (struct X3D_##myType *node){ \
65  float myminx = FLT_MAX; \
66  float mymaxx = -FLT_MAX; \
67  float myminy = FLT_MAX; \
68  float mymaxy = -FLT_MAX; \
69  int count; \
70  \
71  if (node->myField.n<=0) { \
72  node->EXTENT_MIN_X = 0.0f; \
73  node->EXTENT_MAX_X = 0.0f; \
74  node->EXTENT_MIN_Y = 0.0f; \
75  node->EXTENT_MAX_Y = 0.0f; \
76  } else { \
77  for (count = 0; count < node->myField.n; count++) { \
78  if (node->myField.p[count].c[0] > mymaxx) mymaxx = node->myField.p[count].c[0]; \
79  if (node->myField.p[count].c[0] < myminx) myminx = node->myField.p[count].c[0]; \
80  if (node->myField.p[count].c[1] > mymaxy) mymaxy = node->myField.p[count].c[1]; \
81  if (node->myField.p[count].c[1] < myminy) myminy = node->myField.p[count].c[1]; \
82  } \
83  node->EXTENT_MAX_X = mymaxx; \
84  node->EXTENT_MIN_X = myminx; \
85  node->EXTENT_MAX_Y = mymaxy; \
86  node->EXTENT_MIN_Y = myminy; \
87  } \
88  \
89  MARK_NODE_COMPILED \
90 }
91 /***********************************************************************************/
92 
93 void compile_Arc2D (struct X3D_Arc2D *node) {
94  /* have to regen the shape*/
95  struct SFVec2f *tmpptr_a, *tmpptr_b;
96  int tmpint;
97 
98  MARK_NODE_COMPILED
99 
100  tmpint = 0;
101  tmpptr_a = createLines (node->startAngle, node->endAngle, node->radius, NONE, &tmpint, node->_extent);
102 
103  /* perform the switch - worry about threading here without locking */
104  node->__numPoints = 0; /* tell us that it has zero points */
105  tmpptr_b = node->__points.p; /* old set of points, for freeing later */
106  node->__points.p = tmpptr_a; /* new points */
107  node->__numPoints = tmpint;
108  FREE_IF_NZ (tmpptr_b);
109  /* switch completed */
110 
111 }
112 
113 void render_Arc2D (struct X3D_Arc2D *node) {
114  ttglobal tg = gglobal();
115  COMPILE_IF_REQUIRED
116  if (node->__numPoints>0) {
117  /* for BoundingBox calculations */
118  setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
119  node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
120 
121  LIGHTING_OFF
122  DISABLE_CULL_FACE
123 
124  FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->__points.p);
125  sendArraysToGPU (GL_LINE_STRIP, 0, node->__numPoints);
126  tg->Mainloop.trisThisLoop += node->__numPoints;
127  }
128 }
129 
130 /***********************************************************************************/
131 
132 void compile_ArcClose2D (struct X3D_ArcClose2D *node) {
133  //int xx;
134  char *ct;
135  struct SFVec2f *tmpptr_a, *tmpptr_b;
136  int tmpint;
137 
138  /* have to regen the shape*/
139  MARK_NODE_COMPILED
140 
141  ct = node->closureType->strptr;
142  //xx = node->closureType->len;
143  tmpint = 0;
144  tmpptr_a = NULL;
145 
146  if (strcmp(ct,"PIE") == 0) {
147  tmpptr_a = createLines (node->startAngle,
148  node->endAngle, node->radius, PIE, &tmpint,node->_extent);
149  } else if (strcmp(ct,"CHORD") == 0) {
150  tmpptr_a = createLines (node->startAngle,
151  node->endAngle, node->radius, CHORD, &tmpint,node->_extent);
152  } else {
153  printf ("ArcClose2D, closureType %s invalid\n",node->closureType->strptr);
154  }
155 
156  /* perform the switch - worry about threading here without locking */
157  node->__numPoints = 0; /* tell us that it has zero points */
158  tmpptr_b = node->__points.p; /* old set of points, for freeing later */
159  node->__points.p = tmpptr_a; /* new points */
160  node->__numPoints = tmpint;
161  FREE_IF_NZ (tmpptr_b);
162  /* switch completed */
163 }
164 
165 
166 void render_ArcClose2D (struct X3D_ArcClose2D *node) {
167  ttglobal tg = gglobal();
168  COMPILE_IF_REQUIRED
169  if (node->__numPoints>0) {
170  /* for BoundingBox calculations */
171  setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
172  node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
173 
174  LIGHTING_OFF
175  DISABLE_CULL_FACE
176 
177 
178  FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->__points.p);
179  sendArraysToGPU (GL_LINE_STRIP, 0, node->__numPoints);
180 
181  gglobal()->Mainloop.trisThisLoop += node->__numPoints;
182  }
183 }
184 // rendray_ArcClose2D
185 
186 /***********************************************************************************/
187 
188 void compile_Circle2D (struct X3D_Circle2D *node) {
189  struct SFVec2f *tmpptr_a, *tmpptr_b;
190  int tmpint;
191 
192  /* have to regen the shape*/
193  MARK_NODE_COMPILED
194 
195  tmpptr_a = createLines (0.0f, 0.0f, node->radius, NONE, &tmpint,node->_extent);
196 
197  /* perform the switch - worry about threading here without locking */
198  node->__numPoints = 0; /* tell us that it has zero points */
199  tmpptr_b = node->__points.p; /* old set of points, for freeing later */
200  node->__points.p = tmpptr_a; /* new points */
201  node->__numPoints = tmpint;
202  FREE_IF_NZ (tmpptr_b);
203  /* switch completed */
204 }
205 
206 void render_Circle2D (struct X3D_Circle2D *node) {
207  ttglobal tg = gglobal();
208  COMPILE_IF_REQUIRED
209  if (node->__numPoints>0) {
210  /* for BoundingBox calculations */
211  setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
212  node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
213 
214  LIGHTING_OFF
215  DISABLE_CULL_FACE
216 
217  FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->__points.p);
218  sendArraysToGPU (GL_LINE_STRIP, 0, node->__numPoints);
219  gglobal()->Mainloop.trisThisLoop += node->__numPoints;
220  }
221 }
222 
223 /***********************************************************************************/
224 
225 
226 COMPILE_AND_GET_BOUNDS(Polyline2D,lineSegments)
227 
228 void render_Polyline2D (struct X3D_Polyline2D *node){
229  ttglobal tg = gglobal();
230 
231  COMPILE_IF_REQUIRED
232  if (node->lineSegments.n>0) {
233  /* for BoundingBox calculations */
234  setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
235  node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
236 
237  LIGHTING_OFF
238  DISABLE_CULL_FACE
239 
240 
241  FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->lineSegments.p);
242  sendArraysToGPU (GL_LINE_STRIP, 0, node->lineSegments.n);
243  gglobal()->Mainloop.trisThisLoop += node->lineSegments.n;
244  }
245 }
246 
247 /***********************************************************************************/
248 
249 COMPILE_AND_GET_BOUNDS(Polypoint2D,point)
250 
251 void render_Polypoint2D (struct X3D_Polypoint2D *node){
252  ttglobal tg = gglobal();
253 
254  COMPILE_IF_REQUIRED
255  if (node->point.n>0) {
256  /* for BoundingBox calculations */
257  setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
258  node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
259 
260  LIGHTING_OFF
261  DISABLE_CULL_FACE
262 
263 
264  FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->point.p);
265  sendArraysToGPU (GL_POINTS, 0, node->point.n);
266  gglobal()->Mainloop.trisThisLoop += node->point.n;
267  }
268 }
269 
270 /***********************************************************************************/
271 #define DESIRE(whichOne,zzz) ((whichOne & zzz)==zzz)
272 void compile_Disk2D (struct X3D_Disk2D *node){
273  /* have to regen the shape*/
274  struct SFVec2f *fp, *tp;
275  //GLfloat *tp;
276  struct SFVec2f *sfp, *stp;
277  //GLfloat *stp;
278  struct SFVec2f *ofp, *otp;
279  //GLfloat *otp;
280  int i,j,k;
281  GLfloat id;
282  GLfloat od;
283  int tmpint;
284  int simpleDisc;
285  ushort *lindex;
286 
287  MARK_NODE_COMPILED
288 
289 
290  /* bounds checking */
291  if (node->innerRadius<0) {node->__numPoints = 0; return;}
292  if (node->outerRadius<0) {node->__numPoints = 0; return;}
293 
294  /* is this a simple disc ? */
295  if ((APPROX (node->innerRadius, 0.0)) ||
296  (APPROX(node->innerRadius,node->outerRadius))) simpleDisc = TRUE;
297  else simpleDisc = FALSE;
298 
299  /* is this a simple disk, or one with an inner circle cut out? */
300  if (simpleDisc) {
301  tmpint = SEGMENTS_PER_CIRCLE+2;
302  fp = sfp = MALLOC (struct SFVec2f *, sizeof(struct SFVec2f) * (tmpint));
303  tp = stp = MALLOC (struct SFVec2f *, sizeof(struct SFVec2f) * (tmpint)); //(GLfloat *, sizeof(GLfloat) * 2 * (tmpint));
304  lindex = MALLOC (ushort *, sizeof(ushort) * (tmpint*2)*2); //over malloc by a few. should be nsegs * 2 lines/seg * 2 lineEnds/line
305  //if(!node->_gc) node->_gc = newVector(void *,4); H: FreeWRLPTR gets freed, no need for _gc
306  //vector_pushBack(void*,node->_gc,lindex);
307 
308  /* initial TriangleFan point */
309  (*fp).c[0] = 0.0f; (*fp).c[1] = 0.0f; fp++;
310  (*tp).c[0] = 0.5f; (*tp).c[1] = 0.5f; tp++;
311  id = 2.0f;
312 
313  for (i=SEGMENTS_PER_CIRCLE,j=1,k=0; i >= 0; i--,j++,k+=4) {
314  (*fp).c[0] = node->outerRadius * sinf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
315  (*fp).c[1] = node->outerRadius * cosf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
316  fp++;
317 
318  lindex[k + 0] = 0;
319  lindex[k + 1] = j;
320  lindex[k + 2] = j;
321  lindex[k + 3] = j+1;
322 
323  (*tp).c[0] = 0.5f + (sinf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/id);
324  (*tp).c[1] = 0.5f + (cosf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/id);
325  tp++;
326  }
327  node->__wireindices = lindex;
328  } else {
329  tmpint = (SEGMENTS_PER_CIRCLE+1) * 2;
330  fp = sfp = MALLOC (struct SFVec2f *, sizeof(struct SFVec2f) * 2 * tmpint);
331  tp = stp = MALLOC (struct SFVec2f *, sizeof(struct SFVec2f) * (tmpint)); //MALLOC (GLfloat *, sizeof(GLfloat) * 2 * tmpint);
332  lindex = MALLOC (ushort *, sizeof(ushort) * (tmpint*2) *2); //over malloc by a few, should be (nseg-1)*4 lines/seg * 2 lineEnds per line
333  //if(!node->_gc) node->_gc = newVector(void *,4);
334  //vector_pushBack(void*,node->_gc,lindex);
335 
336  /* texture scaling params */
337  od = 2.0f;
338  id = node->outerRadius * 2.0f / node->innerRadius;
339 
340  for (i=SEGMENTS_PER_CIRCLE,j=0,k=0; i >= 0; i--,j+=2,k+=8) {
341  (*fp).c[0] = node->innerRadius * (float) sinf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
342  (*fp).c[1] = node->innerRadius * (float) cosf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
343  fp++;
344  (*fp).c[0] = node->outerRadius * (float) sinf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
345  (*fp).c[1] = node->outerRadius * (float) cosf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
346  fp++;
347 
348  lindex[k + 0] = j;
349  lindex[k + 1] = j+1;
350  lindex[k + 2] = j+1;
351  lindex[k + 3] = j+2;
352  lindex[k + 4] = j+2;
353  lindex[k + 5] = j;
354  lindex[k + 6] = j+1;
355  lindex[k + 7] = j+3;
356 
357  (*tp).c[0] = 0.5f + ((float)sinf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/id);
358  (*tp).c[1] = 0.5f + ((float)cosf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/id);
359  tp++;
360  (*tp).c[0] = 0.5f + ((float)sinf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/od);
361  (*tp).c[1] = 0.5f + ((float)cosf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/od);
362  tp++;
363  }
364  node->__wireindices = lindex;
365  }
366 
367 
368  /* compiling done, set up for rendering. thread safe */
369  node->__numPoints = 0;
370  ofp = node->__points.p;
371  otp = node->__texCoords.p;
372  node->__points.p = sfp;
373  node->__texCoords.p = stp;
374  node->__simpleDisk = simpleDisc;
375  node->__numPoints = tmpint;
376  FREE_IF_NZ (ofp);
377  FREE_IF_NZ (otp);
378 
379  /* we can set the extents here... */
380  node->EXTENT_MAX_X = node->outerRadius;
381  node->EXTENT_MIN_X = -node->outerRadius;
382  node->EXTENT_MAX_Y = node->outerRadius;
383  node->EXTENT_MIN_Y = -node->outerRadius;
384 }
385 
386 void render_Disk2D (struct X3D_Disk2D *node){
387  COMPILE_IF_REQUIRED
388  if (node->__numPoints>0) {
389  struct textureVertexInfo mtf = {(GLfloat *)node->__texCoords.p,2,GL_FLOAT,0,NULL,NULL};
390  /* for BoundingBox calculations */
391  setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
392  node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
393 
394  CULL_FACE(node->solid)
395 
396  textureCoord_send(&mtf);
397  FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->__points.p);
398 
399 
400  /* do the array drawing; sides are simple 0-1-2-3, 4-5-6-7, etc quads */
401  if (node->__simpleDisk) {
402  if(DESIRE(getShaderFlags().base,SHADINGSTYLE_WIRE)){
403  //wireframe triangles
404  sendElementsToGPU(GL_LINES,((node->__numPoints-1)*4 -1 ),node->__wireindices); //should be segs x 2 lines/seg = (pts-1) x 2 lines / pt
405  }else{
406  sendArraysToGPU (GL_TRIANGLE_FAN, 0, node->__numPoints);
407  }
408  }
409  else{
410  if(DESIRE(getShaderFlags().base,SHADINGSTYLE_WIRE)){
411  //wireframe triangles
412  sendElementsToGPU(GL_LINES,(node->__numPoints*4 -4 -1),node->__wireindices); //(nseg -1)*4 = (npts-2)*2 = npts*2 -4
413  }else{
414  sendArraysToGPU (GL_TRIANGLE_STRIP, 0, node->__numPoints);
415  }
416  }
417 
418  gglobal()->Mainloop.trisThisLoop += node->__numPoints;
419  }
420 }
421 //rendray_Disk2D
422 
423 /***********************************************************************************/
424 
425 void compile_TriangleSet2D (struct X3D_TriangleSet2D *node){
426  /* have to regen the shape*/
427  GLfloat maxX, minX;
428  GLfloat maxY, minY;
429  GLfloat Ssize, Tsize;
430  int i,j;
431  ushort *lindex;
432  struct SFVec2f *fp; //GLfloat *fp;
433  int tmpint;
434 
435  MARK_NODE_COMPILED
436 
437  /* do we have vertex counts in sets of 3? */
438  if ((node->vertices.n %3) != 0) {
439  printf ("TriangleSet2D, have incorrect vertex count, %d\n",node->vertices.n);
440  node->vertices.n -= node->vertices.n % 3;
441  }
442 
443  /* save this, and tell renderer that this has 0 vertices (threading stuff) */
444  tmpint = node->vertices.n;
445  node->vertices.n = 0;
446 
447  /* ok, now if renderer renders (threading) it'll see zero, so we are safe */
448  FREE_IF_NZ (node->__texCoords.p);
449  node->__texCoords.p = fp = MALLOC (struct SFVec2f *, sizeof(struct SFVec2f) * (tmpint)); //MALLOC (GLfloat *, sizeof (GLfloat) * tmpint * 2);
450  node->__texCoords.n = tmpint;
451  node->__wireindices = lindex = MALLOC (ushort *, sizeof(ushort)*(tmpint+1)*2); //over malloc a bit, should be: pts = lines, lines * 2 ends/line
452  /* find min/max values for X and Y axes */
453  minY = minX = FLT_MAX;
454  maxY = maxX = -FLT_MAX;
455  for (i=0; i<tmpint; i++) {
456  if (node->vertices.p[i].c[0] < minX) minX = node->vertices.p[i].c[0];
457  if (node->vertices.p[i].c[1] < minY) minY = node->vertices.p[i].c[1];
458  if (node->vertices.p[i].c[0] > maxX) maxX = node->vertices.p[i].c[0];
459  if (node->vertices.p[i].c[1] > maxY) maxY = node->vertices.p[i].c[1];
460  }
461 
462  /* save these numbers for extents */
463  node->EXTENT_MAX_X = maxX;
464  node->EXTENT_MIN_X = minX;
465  node->EXTENT_MAX_Y = maxY;
466  node->EXTENT_MIN_Y = minY;
467 
468  /* printf ("minX %f maxX %f minY %f maxY %f\n",minX, maxX, minY, maxY); */
469  Ssize = maxX - minX;
470  Tsize = maxY - minY;
471  /* printf ("ssize %f tsize %f\n",Ssize, Tsize); */
472 
473  for (i=0,j=0; i<tmpint/3; i++,j+=6) {
474  //wireframe indices
475  int i3 = i*3;
476  lindex[j + 0] = i3;
477  lindex[j + 1] = i3+1;
478  lindex[j + 2] = i3+1;
479  lindex[j + 3] = i3+2;
480  lindex[j + 4] = i3+2;
481  lindex[j + 5] = i3;
482  }
483 
484  for (i=0; i<tmpint; i++) {
485  (*fp).c[0] = (node->vertices.p[i].c[0] - minX) / Ssize;
486  (*fp).c[1] = (node->vertices.p[i].c[1] - minY) / Tsize;
487  fp++;
488  }
489 
490  /* restore, so we know how many tris there are */
491  node->vertices.n = tmpint;
492 }
493 
494 void render_TriangleSet2D (struct X3D_TriangleSet2D *node){
495  COMPILE_IF_REQUIRED
496  if (node->vertices.n>0) {
497  struct textureVertexInfo mtf = {(GLfloat *)node->__texCoords.p,2,GL_FLOAT,0,NULL,NULL};
498  /* for BoundingBox calculations */
499  setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
500  node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
501 
502  CULL_FACE(node->solid)
503 
504  textureCoord_send(&mtf);
505  FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->vertices.p);
506 
507 
508  if(DESIRE(getShaderFlags().base,SHADINGSTYLE_WIRE)){
509  //wireframe triangles
510  sendElementsToGPU(GL_LINES,(node->vertices.n*2),node->__wireindices); //(nseg -1)*4 = (npts-2)*2 = npts*2 -4
511  }else{
512  sendArraysToGPU (GL_TRIANGLES, 0, node->vertices.n);
513  }
514 
515  gglobal()->Mainloop.trisThisLoop += node->vertices.n;
516  }
517 }
518 //rendray_TriangleSet2D
519 
520 
521 /***********************************************************************************/
522 
523 
524 /* this code is remarkably like Box, but with a zero z axis. */
525 void compile_Rectangle2D (struct X3D_Rectangle2D *node) {
526  float *pt;
527  struct SFVec3f *ptr;
528  float x = ((node->size).c[0])/2;
529  float y = ((node->size).c[1])/2;
530 
531  MARK_NODE_COMPILED
532 
533  /* MALLOC memory (if possible)*/
534  if (!node->__points.p) ptr = MALLOC (struct SFVec3f *,sizeof(struct SFVec3f)*(6));
535  else ptr = node->__points.p;
536 
537  /* now, create points; 6 points per face.*/
538  pt = (float *) ptr;
539  #define PTF0 *pt++ = x; *pt++ = y; *pt++ = 0.0f;
540  #define PTF1 *pt++ = -x; *pt++ = y; *pt++ = 0.0f;
541  #define PTF2 *pt++ = -x; *pt++ = -y; *pt++ = 0.0f;
542  #define PTF3 *pt++ = x; *pt++ = -y; *pt++ = 0.0f;
543 
544  PTF0 PTF1 PTF2 PTF0 PTF2 PTF3 /* front */
545  /* finished, and have good data */
546  node->__points.p = (struct SFVec3f*) ptr;
547 
548  #undef PTF0
549  #undef PTF1
550  #undef PTF2
551  #undef PTF3
552 }
553 
554 
555 void render_Rectangle2D (struct X3D_Rectangle2D *node) {
556  extern GLfloat boxtex[]; /* in CFuncs/statics.c*/
557  extern GLfloat boxnorms[]; /* in CFuncs/statics.c*/
558  struct textureVertexInfo mtf = {boxtex,2,GL_FLOAT,0,NULL,NULL};
559 
560  float x = ((node->size).c[0])/2;
561  float y = ((node->size).c[1])/2;
562 
563  /* test for <0 of sides */
564  if ((x < 0) || (y < 0)) return;
565 
566  COMPILE_IF_REQUIRED
567  if (!node->__points.p) return; /* still compiling */
568 
569  /* for BoundingBox calculations */
570  setExtent(x,-x,y,-y,0.0f,0.0f,X3D_NODE(node));
571 
572  CULL_FACE(node->solid)
573 
574  /* Draw it; assume VERTEX and NORMALS already defined.*/
575  textureCoord_send(&mtf);
576  FW_GL_VERTEX_POINTER (3,GL_FLOAT,0,(GLfloat *)node->__points.p);
577  FW_GL_NORMAL_POINTER (GL_FLOAT,0,boxnorms);
578 
579  /* do the array drawing; sides are simple 0-1-2-3, 4-5-6-7, etc quads */
580  if(DESIRE(getShaderFlags().base,SHADINGSTYLE_WIRE)){
581  //wireframe triangles
582  static ushort wireindices [] = { 0, 1, 1, 2, 2, 0, 3, 4, 4, 5, 5, 3 };
583  sendElementsToGPU(GL_LINES,6*2,wireindices); //(nseg -1)*4 = (npts-2)*2 = npts*2 -4
584  }else{
585  sendArraysToGPU (GL_TRIANGLES, 0, 6);
586  }
587  gglobal()->Mainloop.trisThisLoop += 2;
588 }
589 // rendray_Rectangle2D
590 
591 /***********************************************************************************/
592 //http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/geometry2D.html#ArcClose2D
593 // "the angle starts at +x and goes toward +y"
594 // y^
595 // | /
596 // | / ) angle
597 // |_____> x
598 static void *createLines (float start, float end, float radius, int closed, int *size, float *_extent) {
599  int i;
600  int isCircle;
601  int numPoints;
602  GLfloat tmp;
603  GLfloat *points;
604  GLfloat *fp;
605  int arcpoints;
606 
607  float myminx = FLT_MAX;
608  float mymaxx = -FLT_MAX;
609  float myminy = FLT_MAX;
610  float mymaxy = -FLT_MAX;
611 
612  *size = 0;
613 
614  /* is this a circle? */
615  isCircle = APPROX(start,end);
616 
617  /* bounds check, and sort values */
618  if ((start < PI*2.0) || (start > PI*2.0)) start = 0.0f;
619  if ((end < PI*2.0) || (end > PI*2.0)) end = (float) (PI/2.0);
620  if (radius<0.0) radius = 1.0f;
621 
622  if (end > start) {
623  tmp = start;
624  start = end;
625  end = tmp;
626  }
627 
628 
629  if (isCircle) {
630  numPoints = SEGMENTS_PER_CIRCLE;
631  closed = NONE; /* this is a circle, CHORD, PIE dont mean anything now */
632  } else {
633  numPoints = (int) ((float)(SEGMENTS_PER_CIRCLE * (start-end))/(PI*2.0f));
634  if (numPoints>SEGMENTS_PER_CIRCLE) numPoints=SEGMENTS_PER_CIRCLE;
635  }
636 
637  /* we always have to draw the line - we have a line strip, and we calculate
638  the beginning points; we have also to calculate the ending point. */
639  numPoints++;
640  arcpoints = numPoints;
641 
642  /* closure type */
643  if (closed == CHORD) numPoints++;
644  if (closed == PIE) numPoints+=2;
645 
646  points = MALLOC (float *, sizeof(float)*numPoints*2);
647  fp = points;
648 
649  for (i=0; i<arcpoints; i++) {
650  *fp = radius * cosf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
651  fp++;
652  *fp = radius * sinf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
653  fp++;
654  }
655 
656  /* do we have to draw any pies, cords, etc, etc? */
657  if (closed == CHORD) {
658  /* loop back to origin */
659  *fp = radius * cosf(0.0f/((float)SEGMENTS_PER_CIRCLE));
660  fp++;
661  *fp = radius * sinf(0.0f/((float)SEGMENTS_PER_CIRCLE));
662  fp++;
663  } else if (closed == PIE) {
664  /* go to origin */
665  *fp = 0.0f; fp++; *fp=0.0f; fp++;
666  *fp = radius * cosf(0.0f/((float)SEGMENTS_PER_CIRCLE));
667  fp++;
668  *fp = radius * sinf(0.0f/((float)SEGMENTS_PER_CIRCLE));
669  fp++;
670  }
671 
672 
673  /* find extents */
674  *size = numPoints;
675  if (numPoints==0) {
676  EXTENT_MAX_X = 0.0f;
677  EXTENT_MIN_X = 0.0f;
678  EXTENT_MAX_Y = 0.0f;
679  EXTENT_MIN_Y = 0.0f;
680  } else {
681  /* find min/max for setExtent for these points */
682  fp = points;
683  for (i=0; i<numPoints; i++) {
684  /* do X first */
685  if (*fp > mymaxx) mymaxx = *fp;
686  if (*fp < myminx) myminx = *fp;
687  fp++;
688  /* do Y second */
689  if (*fp > mymaxy) mymaxy = *fp;
690  if (*fp < myminy) myminy = *fp;
691  fp++;
692  }
693  EXTENT_MIN_X = myminx;
694  EXTENT_MAX_X = mymaxx;
695  EXTENT_MIN_Y = myminy;
696  EXTENT_MAX_Y = mymaxy;
697  }
698 
699  return (void *)points;
700 }
701 
702 
703 
704 
705 void collide_TriangleSet2D (struct X3D_TriangleSet2D *node) {
706  UNUSED (node);
707 }
708 
709 void collide_Disk2D (struct X3D_Disk2D *node) {
710  UNUSED (node);
711 }
712 
713 void collide_Rectangle2D (struct X3D_Rectangle2D *node) {
714  /* Modified Box code. */
715  struct sNaviInfo *naviinfo;
716  GLDOUBLE awidth, atop, abottom, astep, modelMatrix[16];
717  struct point_XYZ iv = {0,0,0};
718  struct point_XYZ jv = {0,0,0};
719  struct point_XYZ kv = {0,0,0};
720  struct point_XYZ ov = {0,0,0};
721  struct point_XYZ delta;
722 
723  ttglobal tg = gglobal();
724  /*easy access, naviinfo.step unused for sphere collisions */
725  naviinfo = (struct sNaviInfo*)tg->Bindable.naviinfo;
726  awidth = naviinfo->width; /*avatar width*/
727  atop = naviinfo->width; /*top of avatar (relative to eyepoint)*/
728  abottom = -naviinfo->height; /*bottom of avatar (relative to eyepoint)*/
729  astep = -naviinfo->height+naviinfo->step;
730 
731 
732  iv.x = node->size.c[0];
733  jv.y = node->size.c[1];
734  kv.z = 0.0;
735  ov.x = -((node->size).c[0])/2; ov.y = -((node->size).c[1])/2; ov.z = 0.0;
736 
737  /* get the transformed position of the Box, and the scale-corrected radius. */
738  FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, modelMatrix);
739 
740  matmultiplyAFFINE(modelMatrix,modelMatrix,FallInfo()->avatar2collision);
741  //dug9july2011 matmultiply(modelMatrix,FallInfo()->avatar2collision,modelMatrix);
742 
743  {
744  /* minimum bounding box MBB test in avatar/collision space */
745  GLDOUBLE shapeMBBmin[3], shapeMBBmax[3];
746  int i;
747  for(i=0;i<3;i++)
748  {
749  shapeMBBmin[i] = DOUBLE_MIN(-(node->size).c[i]*.5,(node->size).c[i]*.5);
750  shapeMBBmax[i] = DOUBLE_MAX(-(node->size).c[i]*.5,(node->size).c[i]*.5);
751  }
752  if(!avatarCollisionVolumeIntersectMBB(modelMatrix, shapeMBBmin, shapeMBBmax))return;
753  }
754  /* get transformed box edges and position */
755  transform(&ov,&ov,modelMatrix);
756  transform3x3(&iv,&iv,modelMatrix);
757  transform3x3(&jv,&jv,modelMatrix);
758  transform3x3(&kv,&kv,modelMatrix);
759 
760  delta = box_disp(abottom,atop,astep,awidth,ov,iv,jv,kv);
761 
762  vecscale(&delta,&delta,-1);
763 
764  accumulate_disp(CollisionInfo(),delta);
765 
766 
767  #ifdef COLLISIONVERBOSE
768  if((fabs(delta.x) != 0. || fabs(delta.y) != 0. || fabs(delta.z) != 0.))
769  printf("COLLISION_BOX: (%f %f %f) (%f %f %f)\n",
770  ov.x, ov.y, ov.z,
771  delta.x, delta.y, delta.z
772  );
773  if((fabs(delta.x != 0.) || fabs(delta.y != 0.) || fabs(delta.z) != 0.))
774  printf("iv=(%f %f %f) jv=(%f %f %f) kv=(%f %f %f)\n",
775  iv.x, iv.y, iv.z,
776  jv.x, jv.y, jv.z,
777  kv.x, kv.y, kv.z
778  );
779  #endif
780 }