1 /**************************************************************************\
2 * Copyright (c) Kongsberg Oil & Gas Technologies AS
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of the copyright holder nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32
33 // This is an internal class with utility functions we use when
34 // playing around with OpenGL.
35
36 // *************************************************************************
37
38 #include "rendering/SoGL.h"
39 #include "coindefs.h"
40
41 #include <cassert>
42 #include <cstdio>
43 #include <cstring>
44
45 #ifdef HAVE_CONFIG_H
46 #include "config.h"
47 #endif // HAVE_CONFIG_H
48
49 #include <Inventor/C/tidbits.h>
50 #include <Inventor/SoOffscreenRenderer.h>
51 #include <Inventor/actions/SoGLRenderAction.h>
52 #include <Inventor/bundles/SoMaterialBundle.h>
53 #include <Inventor/bundles/SoTextureCoordinateBundle.h>
54 #include <Inventor/bundles/SoVertexAttributeBundle.h>
55 #include <Inventor/elements/SoCacheElement.h>
56 #include <Inventor/elements/SoComplexityElement.h>
57 #include <Inventor/elements/SoComplexityTypeElement.h>
58 #include <Inventor/elements/SoCoordinateElement.h>
59 #include <Inventor/elements/SoGLCacheContextElement.h>
60 #include <Inventor/elements/SoGLCoordinateElement.h>
61 #include <Inventor/elements/SoGLMultiTextureEnabledElement.h>
62 #include <Inventor/elements/SoGLMultiTextureImageElement.h>
63 #include <Inventor/elements/SoModelMatrixElement.h>
64 #include <Inventor/elements/SoMultiTextureEnabledElement.h>
65 #include <Inventor/elements/SoProfileElement.h>
66 #include <Inventor/elements/SoShapeStyleElement.h>
67 #include <Inventor/elements/SoProjectionMatrixElement.h>
68 #include <Inventor/elements/SoMultiTextureCoordinateElement.h>
69 #include <Inventor/elements/SoViewingMatrixElement.h>
70 #include <Inventor/elements/SoViewportRegionElement.h>
71 #include <Inventor/errors/SoDebugError.h>
72 #include <Inventor/lists/SbList.h>
73 #include <Inventor/nodes/SoCallback.h>
74 #include <Inventor/nodes/SoProfile.h>
75 #include <Inventor/nodes/SoShape.h>
76 #include <Inventor/system/gl.h>
77 #include <Inventor/threads/SbStorage.h>
78
79 #include "glue/GLUWrapper.h"
80 #include "tidbitsp.h"
81 #include "glue/glp.h"
82
83 // *************************************************************************
84
85 // Convenience function for access to OpenGL wrapper from an SoState
86 // pointer.
87 const cc_glglue *
sogl_glue_instance(const SoState * state)88 sogl_glue_instance(const SoState * state)
89 {
90 SoGLRenderAction * action = (SoGLRenderAction *)state->getAction();
91 // FIXME: disabled until we figure out why this doesn't work on some
92 // Linux systems (gcc 3.2 systems, it seems). pederb, 2003-11-24
93 #if 0
94 assert(action->isOfType(SoGLRenderAction::getClassTypeId()) &&
95 "must have state from SoGLRenderAction to get hold of GL wrapper");
96 return cc_glglue_instance(action->getCacheContext());
97 #else // disabled
98 if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
99 return cc_glglue_instance(action->getCacheContext());
100 }
101 static int didwarn = 0;
102 if (!didwarn) {
103 didwarn = 1;
104 SoDebugError::postWarning("sogl_glue_instance",
105 "Wrong action type detected. Please report this to <coin-support@sim.no>, "
106 "and include information about your system (compiler, Linux version, etc.");
107 }
108 // just return some cc_glglue instance. It usually doesn't matter
109 // that much unless multiple contexts on multiple displays are used.
110 return cc_glglue_instance(1);
111 #endif // workaround version
112 }
113
114
115 // generate a 3d circle in the x-z plane
116 static void
sogl_generate_3d_circle(SbVec3f * coords,const int num,const float radius,const float y)117 sogl_generate_3d_circle(SbVec3f *coords, const int num, const float radius, const float y)
118 {
119 float delta = 2.0f*float(M_PI)/float(num);
120 float angle = 0.0f;
121 for (int i = 0; i < num; i++) {
122 coords[i][0] = -float(sin(angle)) * radius;
123 coords[i][1] = y;
124 coords[i][2] = -float(cos(angle)) * radius;
125 angle += delta;
126 }
127 }
128
129 // generate a 2d circle
130 static void
sogl_generate_2d_circle(SbVec2f * coords,const int num,const float radius)131 sogl_generate_2d_circle(SbVec2f *coords, const int num, const float radius)
132 {
133 float delta = 2.0f*float(M_PI)/float(num);
134 float angle = 0.0f;
135 for (int i = 0; i < num; i++) {
136 coords[i][0] = -float(sin(angle)) * radius;
137 coords[i][1] = -float(cos(angle)) * radius;
138 angle += delta;
139 }
140 }
141
142 void
sogl_render_cone(const float radius,const float height,const int numslices,SoMaterialBundle * const material,const unsigned int flagsin,SoState * state)143 sogl_render_cone(const float radius,
144 const float height,
145 const int numslices,
146 SoMaterialBundle * const material,
147 const unsigned int flagsin,
148 SoState * state)
149 {
150 const SbBool * unitenabled = NULL;
151 int maxunit = 0;
152 const cc_glglue * glue = NULL;
153
154 int flags = flagsin;
155
156 if (state) {
157 unitenabled =
158 SoMultiTextureEnabledElement::getEnabledUnits(state, maxunit);
159 if (unitenabled) {
160 glue = sogl_glue_instance(state);
161 flags |= SOGL_NEED_MULTITEXCOORDS;
162 }
163 else maxunit = -1;
164 }
165
166 int i,u;
167 // use a limit of 128 to avoid allocating memory each time
168 // a cone is drawn
169 int slices = numslices;
170 if (slices > 128) slices = 128;
171 if (slices < 4) slices = 4;
172
173 float h2 = height * 0.5f;
174
175 // put coordinates on the stack
176 SbVec3f coords[129];
177 SbVec3f normals[130];
178 SbVec2f texcoords[129];
179
180 sogl_generate_3d_circle(coords, slices, radius, -h2);
181 coords[slices] = coords[0];
182 if (flags & (SOGL_NEED_TEXCOORDS|SOGL_NEED_3DTEXCOORDS|SOGL_NEED_MULTITEXCOORDS)) {
183 sogl_generate_2d_circle(texcoords, slices, 0.5f);
184 texcoords[slices] = texcoords[0];
185 }
186
187 if (flags & SOGL_NEED_NORMALS) {
188 double a = atan(height/radius);
189 sogl_generate_3d_circle(normals, slices, float(sin(a)), float(cos(a)));
190 normals[slices] = normals[0];
191 normals[slices+1] = normals[1];
192 }
193
194 int matnr = 0;
195
196 // FIXME: the texture coordinate generation for cone sides is of
197 // sub-par quality. The textures comes out looking "skewed" and
198 // "compressed". 20010926 mortene.
199
200 if (flags & SOGL_RENDER_SIDE) {
201 glBegin(GL_TRIANGLES);
202 i = 0;
203
204 float t = 1.0;
205 float delta = 1.0f / slices;
206
207 while (i < slices) {
208 if (flags & SOGL_NEED_TEXCOORDS) {
209 glTexCoord2f(t - delta*0.5f, 1.0f);
210 }
211 else if (flags & SOGL_NEED_3DTEXCOORDS) {
212 glTexCoord3f(0.5f, 1.0f, 0.5f);
213 }
214 if (flags & SOGL_NEED_NORMALS) {
215 SbVec3f n = (normals[i] + normals[i+1])*0.5f;
216 glNormal3f(n[0], n[1], n[2]);
217 }
218 if (flags & SOGL_NEED_MULTITEXCOORDS) {
219 for (u = 1; u <= maxunit; u++) {
220 if (unitenabled[u]) {
221 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
222 t - delta*0.5f, 1.0f);
223 }
224 }
225 }
226
227 glVertex3f(0.0f, h2, 0.0f);
228 if (flags & SOGL_NEED_TEXCOORDS) {
229 glTexCoord2f(t, 0.0f);
230 }
231 else if (flags & SOGL_NEED_3DTEXCOORDS) {
232 glTexCoord3f(texcoords[i][0]+0.5f, 0.0f, texcoords[i][1]+0.5f);
233 }
234 if (flags & SOGL_NEED_NORMALS) {
235 glNormal3fv((const GLfloat*)&normals[i]);
236 }
237 if (flags & SOGL_NEED_MULTITEXCOORDS) {
238 for (u = 1; u <= maxunit; u++) {
239 if (unitenabled[u]) {
240 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
241 t, 0.0f);
242 }
243 }
244 }
245 glVertex3fv((const GLfloat*)&coords[i]);
246
247 if (flags & SOGL_NEED_TEXCOORDS) {
248 glTexCoord2f(t - delta, 0.0f);
249 }
250 else if (flags & SOGL_NEED_3DTEXCOORDS) {
251 glTexCoord3f(texcoords[i+1][0]+0.5f, 0.0f, texcoords[i+1][1]+0.5f);
252 }
253 if (flags & SOGL_NEED_NORMALS) {
254 glNormal3fv((const GLfloat*)&normals[i+1]);
255 }
256 if (flags & SOGL_NEED_MULTITEXCOORDS) {
257 for (u = 1; u <= maxunit; u++) {
258 if (unitenabled[u]) {
259 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
260 t - delta, 0.0f);
261 }
262 }
263 }
264 glVertex3fv((const GLfloat*)&coords[i+1]);
265
266 i++;
267 t -= delta;
268 }
269
270 matnr++;
271 glEnd();
272 }
273
274 if (flags & SOGL_RENDER_BOTTOM) {
275 if (flags & SOGL_MATERIAL_PER_PART) {
276 material->send(matnr, TRUE);
277 }
278
279 glBegin(GL_TRIANGLE_FAN);
280 glNormal3f(0.0f, -1.0f, 0.0f);
281 for (i = slices-1; i >= 0; i--) {
282 if (flags & SOGL_NEED_TEXCOORDS) {
283 glTexCoord2f(texcoords[i][0]+0.5f, texcoords[i][1]+0.5f);
284 }
285 else if (flags & SOGL_NEED_3DTEXCOORDS) {
286 glTexCoord3f(texcoords[i][0]+0.5f, 0.0f, texcoords[i][1]+0.5f);
287 }
288 if (flags & SOGL_NEED_MULTITEXCOORDS) {
289 for (u = 1; u <= maxunit; u++) {
290 if (unitenabled[u]) {
291 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
292 texcoords[i][0]+0.5f, texcoords[i][1]+0.5f);
293 }
294 }
295 }
296
297 glVertex3fv((const GLfloat*)&coords[i]);
298 }
299 glEnd();
300 }
301 if (state && (SoComplexityTypeElement::get(state) ==
302 SoComplexityTypeElement::OBJECT_SPACE)) {
303 // encourage auto caching for object space
304 SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DO_AUTO_CACHE);
305 SoGLCacheContextElement::incNumShapes(state);
306 }
307 else {
308 SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE);
309 }
310 }
311
312 void
sogl_render_cylinder(const float radius,const float height,const int numslices,SoMaterialBundle * const material,const unsigned int flagsin,SoState * state)313 sogl_render_cylinder(const float radius,
314 const float height,
315 const int numslices,
316 SoMaterialBundle * const material,
317 const unsigned int flagsin,
318 SoState * state)
319 {
320 const SbBool * unitenabled = NULL;
321 int maxunit = 0;
322 const cc_glglue * glue = NULL;
323
324 int flags = flagsin;
325
326 if (state) {
327 unitenabled =
328 SoMultiTextureEnabledElement::getEnabledUnits(state, maxunit);
329 if (unitenabled) {
330 glue = sogl_glue_instance(state);
331 flags |= SOGL_NEED_MULTITEXCOORDS;
332 }
333 else maxunit = -1;
334 }
335
336 int i, u;
337 int slices = numslices;
338 if (slices > 128) slices = 128;
339 if (slices < 4) slices = 4;
340
341 float h2 = height * 0.5f;
342
343 SbVec3f coords[129];
344 SbVec3f normals[130];
345 SbVec2f texcoords[129];
346
347 sogl_generate_3d_circle(coords, slices, radius, -h2);
348 coords[slices] = coords[0];
349 if (flags & SOGL_NEED_3DTEXCOORDS ||
350 (flags & SOGL_NEED_TEXCOORDS &&
351 flags & (SOGL_RENDER_BOTTOM | SOGL_RENDER_TOP))) {
352 sogl_generate_2d_circle(texcoords, slices, 0.5f);
353 texcoords[slices] = texcoords[0];
354 }
355
356 if (flags & SOGL_NEED_NORMALS) {
357 sogl_generate_3d_circle(normals, slices, 1.0f, 0.0f);
358 normals[slices] = normals[0];
359 normals[slices+1] = normals[1];
360 }
361
362 int matnr = 0;
363
364 if (flags & SOGL_RENDER_SIDE) {
365 glBegin(GL_QUAD_STRIP);
366 i = 0;
367
368 float t = 0.0;
369 float inc = 1.0f / slices;
370
371 while (i <= slices) {
372 if (flags & SOGL_NEED_TEXCOORDS) {
373 glTexCoord2f(t, 1.0f);
374 }
375 else if (flags & SOGL_NEED_3DTEXCOORDS) {
376 glTexCoord3f(texcoords[i][0]+0.5f, 1.0f, 1.0f - texcoords[i][1]-0.5f);
377 }
378 if (flags & SOGL_NEED_NORMALS) {
379 glNormal3fv((const GLfloat*)&normals[i]);
380 }
381 if (flags & SOGL_NEED_MULTITEXCOORDS) {
382 for (u = 1; u <= maxunit; u++) {
383 if (unitenabled[u]) {
384 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
385 t, 1.0f);
386 }
387 }
388 }
389
390 SbVec3f c = coords[i];
391 glVertex3f(c[0], h2, c[2]);
392 if (flags & SOGL_NEED_TEXCOORDS) {
393 glTexCoord2f(t, 0.0f);
394 }
395 else if (flags & SOGL_NEED_3DTEXCOORDS) {
396 glTexCoord3f(texcoords[i][0]+0.5f, 0.0f, 1.0f - texcoords[i][1]-0.5f);
397 }
398 if (flags & SOGL_NEED_MULTITEXCOORDS) {
399 for (u = 1; u <= maxunit; u++) {
400 if (unitenabled[u]) {
401 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
402 t, 0.0f);
403 }
404 }
405 }
406 glVertex3f(c[0], c[1], c[2]);
407 i++;
408 t += inc;
409 }
410
411 matnr++;
412 glEnd();
413 }
414
415 if ((flags & (SOGL_NEED_TEXCOORDS|SOGL_NEED_3DTEXCOORDS|SOGL_NEED_MULTITEXCOORDS)) &&
416 (flags & (SOGL_RENDER_BOTTOM | SOGL_RENDER_TOP))) {
417 sogl_generate_2d_circle(texcoords, slices, 0.5f);
418 texcoords[slices] = texcoords[0];
419 }
420
421 if (flags & SOGL_RENDER_TOP) {
422 if (flags & SOGL_MATERIAL_PER_PART) {
423 material->send(matnr, TRUE);
424 }
425 glBegin(GL_TRIANGLE_FAN);
426 glNormal3f(0.0f, 1.0f, 0.0f);
427
428 for (i = 0; i < slices; i++) {
429 if (flags & SOGL_NEED_TEXCOORDS) {
430 glTexCoord2f(texcoords[i][0]+0.5f, 1.0f - texcoords[i][1]-0.5f);
431 }
432 else if (flags & SOGL_NEED_3DTEXCOORDS) {
433 glTexCoord3f(texcoords[i][0]+0.5f, 1.0f, 1.0f - texcoords[i][1]-0.5f);
434 }
435 if (flags & SOGL_NEED_MULTITEXCOORDS) {
436 for (u = 1; u <= maxunit; u++) {
437 if (unitenabled[u]) {
438 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
439 texcoords[i][0]+0.5f, 1.0f - texcoords[i][1]-0.5f);
440 }
441 }
442 }
443 const SbVec3f &c = coords[i];
444 glVertex3f(c[0], h2, c[2]);
445 }
446 glEnd();
447 matnr++;
448 }
449 if (flags & SOGL_RENDER_BOTTOM) {
450 if (flags & SOGL_MATERIAL_PER_PART) {
451 material->send(matnr, TRUE);
452 }
453 glBegin(GL_TRIANGLE_FAN);
454 glNormal3f(0.0f, -1.0f, 0.0f);
455
456 for (i = slices-1; i >= 0; i--) {
457 if (flags & SOGL_NEED_TEXCOORDS) {
458 glTexCoord2f(texcoords[i][0]+0.5f, texcoords[i][1]+0.5f);
459 }
460 else if (flags & SOGL_NEED_3DTEXCOORDS) {
461 glTexCoord3f(texcoords[i][0]+0.5f, 0.0f, 1.0f - texcoords[i][1]-0.5f);
462 }
463 if (flags & SOGL_NEED_MULTITEXCOORDS) {
464 for (u = 1; u <= maxunit; u++) {
465 if (unitenabled[u]) {
466 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
467 texcoords[i][0]+0.5f, texcoords[i][1]+0.5f);
468 }
469 }
470 }
471 glVertex3fv((const GLfloat*)&coords[i]);
472 }
473 glEnd();
474 }
475 if (state && (SoComplexityTypeElement::get(state) ==
476 SoComplexityTypeElement::OBJECT_SPACE)) {
477 // encourage auto caching for object space
478 SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DO_AUTO_CACHE);
479 SoGLCacheContextElement::incNumShapes(state);
480 }
481 else {
482 SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE);
483 }
484 }
485
486 void
sogl_render_sphere(const float radius,const int numstacks,const int numslices,SoMaterialBundle * const,const unsigned int flagsin,SoState * state)487 sogl_render_sphere(const float radius,
488 const int numstacks,
489 const int numslices,
490 SoMaterialBundle * const /* material */,
491 const unsigned int flagsin,
492 SoState * state)
493 {
494 const SbBool * unitenabled = NULL;
495 int maxunit = 0;
496 const cc_glglue * glue = NULL;
497
498 unsigned int flags = flagsin;
499
500 if (state && (flags & SOGL_NEED_TEXCOORDS)) {
501 unitenabled =
502 SoMultiTextureEnabledElement::getEnabledUnits(state, maxunit);
503 if (unitenabled) {
504 glue = sogl_glue_instance(state);
505 flags |= SOGL_NEED_MULTITEXCOORDS;
506 }
507 else maxunit = -1;
508 }
509
510 int stacks = numstacks;
511 int slices = numslices;
512
513 if (stacks < 3) stacks = 3;
514 if (slices < 4) slices = 4;
515
516 if (slices > 128) slices = 128;
517
518 // used to cache last stack's data
519 SbVec3f coords[129];
520 SbVec3f normals[129];
521 float S[129];
522 SbVec3f texcoords[129];
523
524 int i, j, u;
525 float rho;
526 float drho;
527 float theta;
528 float dtheta;
529 float tc, ts;
530 SbVec3f tmp;
531
532 drho = float(M_PI) / (float) (stacks-1);
533 dtheta = 2.0f * float(M_PI) / (float) slices;
534
535 float currs = 0.0f;
536 float incs = 1.0f / (float)slices;
537 rho = drho;
538 theta = 0.0f;
539 tc = (float) cos(rho);
540 ts = - (float) sin(rho);
541 tmp.setValue(0.0f,
542 tc,
543 ts);
544 normals[0] = tmp;
545 texcoords[0] = tmp/2 + SbVec3f(0.5f,0.5f,0.5f);
546 tmp *= radius;
547 coords[0] = tmp;
548 S[0] = currs;
549 float dT = 1.0f / (float) (stacks-1);
550 float T = 1.0f - dT;
551
552 glBegin(GL_TRIANGLES);
553
554 for (j = 1; j <= slices; j++) {
555 glNormal3f(0.0f, 1.0f, 0.0f);
556 if (flags & SOGL_NEED_TEXCOORDS) {
557 glTexCoord2f(currs + 0.5f * incs, 1.0f);
558 }
559 else if (flags & SOGL_NEED_3DTEXCOORDS) {
560 glTexCoord3f(0.5f, 1.0f, 0.5f);
561 }
562 if (flags & SOGL_NEED_MULTITEXCOORDS) {
563 for (u = 1; u <= maxunit; u++) {
564 if (unitenabled[u]) {
565 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
566 currs + 0.5f * incs, 1.0f);
567 }
568 }
569 }
570 glVertex3f(0.0f, radius, 0.0f);
571
572 glNormal3fv((const GLfloat*) &normals[j-1]);
573 if (flags & SOGL_NEED_TEXCOORDS) {
574 glTexCoord2f(currs, T);
575 }
576 else if (flags & SOGL_NEED_3DTEXCOORDS) {
577 glTexCoord3fv((const GLfloat*) &texcoords[j-1]);
578 }
579 if (flags & SOGL_NEED_MULTITEXCOORDS) {
580 for (u = 1; u <= maxunit; u++) {
581 if (unitenabled[u]) {
582 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
583 currs, T);
584 }
585 }
586 }
587
588 glVertex3fv((const GLfloat*) &coords[j-1]);
589
590 currs += incs;
591 theta += dtheta;
592 tmp.setValue(float(sin(theta))*ts,
593 tc,
594 float(cos(theta))*ts);
595
596 normals[j] = tmp;
597 glNormal3fv((const GLfloat*)&normals[j]);
598 if (flags & SOGL_NEED_TEXCOORDS) {
599 S[j] = currs;
600 glTexCoord2f(currs, T);
601 }
602 else if (flags & SOGL_NEED_3DTEXCOORDS) {
603 texcoords[j] = tmp/2 + SbVec3f(0.5f,0.5f,0.5f);
604 glTexCoord3fv((const GLfloat*) &texcoords[j]);
605 }
606 if (flags & SOGL_NEED_MULTITEXCOORDS) {
607 for (u = 1; u <= maxunit; u++) {
608 if (unitenabled[u]) {
609 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
610 currs, T);
611 }
612 }
613 }
614 tmp *= radius;
615 coords[j] = tmp;
616 glVertex3fv((const GLfloat*)&coords[j]);
617 }
618 glEnd(); // GL_TRIANGLES
619
620 rho += drho;
621
622 for (i = 2; i < stacks-1; i++) {
623 tc = (float)cos(rho);
624 ts = - (float) sin(rho);
625 glBegin(GL_QUAD_STRIP);
626 theta = 0.0f;
627 for (j = 0; j <= slices; j++) {
628 if (flags & SOGL_NEED_TEXCOORDS) {
629 glTexCoord2f(S[j], T);
630 }
631 else if (flags & SOGL_NEED_3DTEXCOORDS) {
632 glTexCoord3fv((const GLfloat*) &texcoords[j]);
633 }
634 if (flags & SOGL_NEED_MULTITEXCOORDS) {
635 for (u = 1; u <= maxunit; u++) {
636 if (unitenabled[u]) {
637 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
638 S[j], T);
639 }
640 }
641 }
642 glNormal3fv((const GLfloat*)&normals[j]);
643 glVertex3fv((const GLfloat*)&coords[j]);
644
645 tmp.setValue(float(sin(theta))*ts,
646 tc,
647 float(cos(theta))*ts);
648 if (flags & SOGL_NEED_TEXCOORDS) {
649 glTexCoord2f(S[j], T - dT);
650 }
651 else if (flags & SOGL_NEED_3DTEXCOORDS) {
652 texcoords[j] = tmp/2 + SbVec3f(0.5f,0.5f,0.5f);
653 glTexCoord3fv((const GLfloat*) &texcoords[j]);
654 }
655 if (flags & SOGL_NEED_MULTITEXCOORDS) {
656 for (u = 1; u <= maxunit; u++) {
657 if (unitenabled[u]) {
658 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
659 S[j], T - dT);
660 }
661 }
662 }
663 normals[j] = tmp;
664 glNormal3f(tmp[0], tmp[1], tmp[2]);
665 tmp *= radius;
666 glVertex3f(tmp[0], tmp[1], tmp[2]);
667 coords[j] = tmp;
668 theta += dtheta;
669 }
670 glEnd(); // GL_QUAD_STRIP
671 rho += drho;
672 T -= dT;
673 }
674
675 glBegin(GL_TRIANGLES);
676 for (j = 0; j < slices; j++) {
677 if (flags & SOGL_NEED_TEXCOORDS) {
678 glTexCoord2f(S[j], T);
679 }
680 else if (flags & SOGL_NEED_3DTEXCOORDS) {
681 glTexCoord3fv((const GLfloat*) &texcoords[j]);
682 }
683 if (flags & SOGL_NEED_MULTITEXCOORDS) {
684 for (u = 1; u <= maxunit; u++) {
685 if (unitenabled[u]) {
686 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
687 S[j], T);
688 }
689 }
690 }
691 glNormal3fv((const GLfloat*)&normals[j]);
692 glVertex3fv((const GLfloat*)&coords[j]);
693
694 if (flags & SOGL_NEED_TEXCOORDS) {
695 glTexCoord2f(S[j]+incs*0.5f, 0.0f);
696 }
697 else if (flags & SOGL_NEED_3DTEXCOORDS) {
698 glTexCoord3f(0.5f, 0.0f, 0.5f);
699 }
700 if (flags & SOGL_NEED_MULTITEXCOORDS) {
701 for (u = 1; u <= maxunit; u++) {
702 if (unitenabled[u]) {
703 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
704 S[j]+incs*0.5f, 0.0f);
705 }
706 }
707 }
708 glNormal3f(0.0f, -1.0f, 0.0f);
709 glVertex3f(0.0f, -radius, 0.0f);
710
711 if (flags & SOGL_NEED_TEXCOORDS) {
712 glTexCoord2f(S[j+1], T);
713 }
714 else if (flags & SOGL_NEED_3DTEXCOORDS) {
715 glTexCoord3fv((const GLfloat*) &texcoords[j+1]);
716 }
717 if (flags & SOGL_NEED_MULTITEXCOORDS) {
718 for (u = 1; u <= maxunit; u++) {
719 if (unitenabled[u]) {
720 cc_glglue_glMultiTexCoord2f(glue, (GLenum) (GL_TEXTURE0 + u),
721 S[j+1], T);
722 }
723 }
724 }
725 glNormal3fv((const GLfloat*)&normals[j+1]);
726 glVertex3fv((const GLfloat*)&coords[j+1]);
727 }
728 glEnd(); // GL_TRIANGLES
729
730 if (state && (SoComplexityTypeElement::get(state) ==
731 SoComplexityTypeElement::OBJECT_SPACE)) {
732 // encourage auto caching for object space
733 SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DO_AUTO_CACHE);
734 SoGLCacheContextElement::incNumShapes(state);
735 }
736 else {
737 SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE);
738 }
739 }
740
741 //
742 // the 12 triangles in the cube
743 //
744 static int sogl_cube_vindices[] =
745 {
746 0, 1, 3, 2,
747 5, 4, 6, 7,
748 1, 5, 7, 3,
749 4, 0, 2, 6,
750 4, 5, 1, 0,
751 2, 3, 7, 6
752 };
753
754 static float sogl_cube_texcoords[] =
755 {
756 1.0f, 1.0f,
757 0.0f, 1.0f,
758 0.0f, 0.0f,
759 1.0f, 0.0f
760 };
761
762 static float sogl_cube_3dtexcoords[][3] =
763 {
764 {1.0f, 1.0f, 1.0f},
765 {1.0f, 1.0f, 0.0f},
766 {1.0f, 0.0f, 1.0f},
767 {1.0f, 0.0f, 0.0f},
768 {0.0f, 1.0f, 1.0f},
769 {0.0f, 1.0f, 0.0f},
770 {0.0f, 0.0f, 1.0f},
771 {0.0f, 0.0f, 0.0f}
772 };
773
774 static float sogl_cube_normals[] =
775 {
776 0.0f, 0.0f, 1.0f,
777 0.0f, 0.0f, -1.0f,
778 -1.0f, 0.0f, 0.0f,
779 1.0f, 0.0f, 0.0f,
780 0.0f, 1.0f, 0.0f,
781 0.0f, -1.0f, 0.0f
782 };
783
784 static void
sogl_generate_cube_vertices(SbVec3f * varray,const float w,const float h,const float d)785 sogl_generate_cube_vertices(SbVec3f *varray,
786 const float w,
787 const float h,
788 const float d)
789 {
790 for (int i = 0; i < 8; i++) {
791 varray[i].setValue((i&1) ? -w : w,
792 (i&2) ? -h : h,
793 (i&4) ? -d : d);
794 }
795 }
796
797
798 void
sogl_render_cube(const float width,const float height,const float depth,SoMaterialBundle * const material,const unsigned int flagsin,SoState * state)799 sogl_render_cube(const float width,
800 const float height,
801 const float depth,
802 SoMaterialBundle * const material,
803 const unsigned int flagsin,
804 SoState * state)
805 {
806 const SbBool * unitenabled = NULL;
807 int maxunit = 0;
808 const cc_glglue * glue = NULL;
809
810 int flags = flagsin;
811
812 if (state) {
813 unitenabled =
814 SoMultiTextureEnabledElement::getEnabledUnits(state, maxunit);
815 if (unitenabled) {
816 glue = sogl_glue_instance(state);
817 flags |= SOGL_NEED_MULTITEXCOORDS;
818 }
819 else maxunit = -1;
820 }
821
822
823 SbVec3f varray[8];
824 sogl_generate_cube_vertices(varray,
825 width * 0.5f,
826 height * 0.5f,
827 depth * 0.5f);
828 glBegin(GL_QUADS);
829 int *iptr = sogl_cube_vindices;
830 int u;
831
832 for (int i = 0; i < 6; i++) { // 6 quads
833 if (flags & SOGL_NEED_NORMALS)
834 glNormal3fv((const GLfloat*)&sogl_cube_normals[i*3]);
835 if (flags & SOGL_MATERIAL_PER_PART)
836 material->send(i, TRUE);
837 for (int j = 0; j < 4; j++) {
838 if (flags & SOGL_NEED_3DTEXCOORDS) {
839 glTexCoord3fv(sogl_cube_3dtexcoords[*iptr]);
840 }
841 else if (flags & SOGL_NEED_TEXCOORDS) {
842 glTexCoord2fv(&sogl_cube_texcoords[j<<1]);
843 }
844 if (flags & SOGL_NEED_MULTITEXCOORDS) {
845 for (u = 1; u <= maxunit; u++) {
846 if (unitenabled[u]) {
847 cc_glglue_glMultiTexCoord2fv(glue, (GLenum) (GL_TEXTURE0 + u),
848 &sogl_cube_texcoords[j<<1]);
849 }
850 }
851 }
852 glVertex3fv((const GLfloat*)&varray[*iptr++]);
853 }
854 }
855 glEnd();
856
857 if (state) {
858 // always encourage auto caching for cubes
859 SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DO_AUTO_CACHE);
860 SoGLCacheContextElement::incNumShapes(state);
861 }
862 }
863
864 // **************************************************************************
865
866 #if !defined(NO_LINESET_RENDER)
867
868 namespace { namespace SoGL { namespace IndexedLineSet {
869
870 enum AttributeBinding {
871 OVERALL = 0,
872 PER_SEGMENT = 1,
873 PER_SEGMENT_INDEXED = 2,
874 PER_LINE = 3,
875 PER_LINE_INDEXED = 4,
876 PER_VERTEX = 5,
877 PER_VERTEX_INDEXED = 6
878 };
879
880 template < int NormalBinding,
881 int MaterialBinding,
882 int TexturingEnabled >
GLRender(const SoGLCoordinateElement * coords,const int32_t * indices,int num_vertexindices,const SbVec3f * normals,const int32_t * normindices,SoMaterialBundle * const materials,const int32_t * matindices,const SoTextureCoordinateBundle * const texcoords,const int32_t * texindices,const int drawAsPoints)883 static void GLRender(const SoGLCoordinateElement * coords,
884 const int32_t *indices,
885 int num_vertexindices,
886 const SbVec3f *normals,
887 const int32_t *normindices,
888 SoMaterialBundle *const materials,
889 const int32_t *matindices,
890 const SoTextureCoordinateBundle * const texcoords,
891 const int32_t *texindices,
892 const int drawAsPoints)
893 {
894 const SbVec3f * coords3d = NULL;
895 const SbVec4f * coords4d = NULL;
896 const SbBool is3d = coords->is3D();
897 if (is3d) {
898 coords3d = coords->getArrayPtr3();
899 }
900 else {
901 coords4d = coords->getArrayPtr4();
902 }
903 int numcoords = coords->getNum();
904
905 // This is the same code as in SoGLCoordinateElement::send().
906 // It is inlined here for speed (~15% speed increase).
907 #define SEND_VERTEX(_idx_) \
908 if (is3d) glVertex3fv((const GLfloat*) (coords3d + _idx_)); \
909 else glVertex4fv((const GLfloat*) (coords4d + _idx_));
910
911 if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED) {
912 if (matindices == NULL) matindices = indices;
913 }
914 if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED) {
915 if (normindices == NULL) normindices = indices;
916 }
917
918 int matnr = 0;
919 int texidx = 0;
920 int32_t i;
921 const int32_t *end = indices + num_vertexindices;
922
923 SbVec3f dummynormal(0.0f, 0.0f, 1.0f);
924 const SbVec3f *currnormal = &dummynormal;
925 if (normals) currnormal = normals;
926 if ((AttributeBinding)MaterialBinding == OVERALL) {
927 glNormal3fv((const GLfloat*)currnormal);
928 }
929
930 if ((AttributeBinding)MaterialBinding == PER_SEGMENT ||
931 (AttributeBinding)MaterialBinding == PER_SEGMENT_INDEXED ||
932 (AttributeBinding)NormalBinding == PER_SEGMENT ||
933 (AttributeBinding)NormalBinding == PER_SEGMENT_INDEXED) {
934 int previ;
935
936 if (drawAsPoints)
937 glBegin(GL_POINTS);
938 else
939 glBegin(GL_LINES);
940
941 while (indices < end) {
942 previ = *indices++;
943
944 // Variable used for counting errors and make sure not a bunch of
945 // errormessages flood the screen.
946 static uint32_t current_errors = 0;
947
948 // This test is for robustness upon buggy data sets
949 if (previ < 0 || previ >= numcoords) {
950 if (current_errors < 1) {
951 SoDebugError::postWarning("[indexedlineset]::GLRender", "Erroneous coordinate "
952 "index: %d (Should be within [0, %d]). Aborting "
953 "rendering. This message will be shown once, but "
954 "there might be more errors", previ, numcoords - 1);
955 }
956
957 current_errors++;
958 glEnd();
959 return;
960 }
961
962 if ((AttributeBinding)MaterialBinding == PER_LINE ||
963 (AttributeBinding)MaterialBinding == PER_VERTEX) {
964 materials->send(matnr++, TRUE);
965 } else if ((AttributeBinding)MaterialBinding == PER_LINE_INDEXED ||
966 (AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED) {
967 materials->send(*matindices++, TRUE);
968 }
969
970 if ((AttributeBinding)NormalBinding == PER_LINE ||
971 (AttributeBinding)NormalBinding == PER_VERTEX) {
972 currnormal = normals++;
973 glNormal3fv((const GLfloat*) currnormal);
974 } else if ((AttributeBinding)NormalBinding == PER_LINE_INDEXED ||
975 (AttributeBinding)NormalBinding == PER_VERTEX_INDEXED) {
976 currnormal = &normals[*normindices++];
977 glNormal3fv((const GLfloat*) currnormal);
978 }
979 if (TexturingEnabled == TRUE) {
980 texcoords->send(texindices ? *texindices++ : texidx++,coords->get3(previ), *currnormal);
981 }
982 i = (indices < end) ? *indices++ : -1;
983 while (i >= 0) {
984 // For robustness upon buggy data sets
985 if (i >= numcoords) {
986 if (current_errors < 1) {
987 SoDebugError::postWarning("[indexedlineset]::GLRender", "Erroneous coordinate "
988 "index: %d (Should be within [0, %d]). Aborting "
989 "rendering. This message will be shown once, but "
990 "there might be more errors", i, numcoords - 1);
991 }
992 current_errors++;
993 break;
994 }
995
996 if ((AttributeBinding)MaterialBinding == PER_SEGMENT) {
997 materials->send(matnr++, TRUE);
998 } else if ((AttributeBinding)MaterialBinding == PER_SEGMENT_INDEXED) {
999 materials->send(*matindices++, TRUE);
1000 }
1001
1002 if ((AttributeBinding)NormalBinding == PER_SEGMENT) {
1003 currnormal = normals++;
1004 glNormal3fv((const GLfloat*) currnormal);
1005 } else if ((AttributeBinding)NormalBinding == PER_SEGMENT_INDEXED) {
1006 currnormal = &normals[*normindices++];
1007 glNormal3fv((const GLfloat*)currnormal);
1008 }
1009 SEND_VERTEX(previ);
1010
1011 if ((AttributeBinding)MaterialBinding == PER_VERTEX) {
1012 materials->send(matnr++, TRUE);
1013 } else if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED) {
1014 materials->send(*matindices++, TRUE);
1015 }
1016 if ((AttributeBinding)NormalBinding == PER_VERTEX) {
1017 currnormal = normals++;
1018 glNormal3fv((const GLfloat*)currnormal);
1019 } else if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED) {
1020 currnormal = &normals[*normindices++];
1021 glNormal3fv((const GLfloat*)currnormal);
1022 }
1023 if (TexturingEnabled == TRUE) {
1024 texcoords->send(texindices ? *texindices++ : texidx++, coords->get3(i), *currnormal);
1025 }
1026 SEND_VERTEX(i);
1027 previ = i;
1028 i = indices < end ? *indices++ : -1;
1029 }
1030 if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED) {
1031 matindices++;
1032 }
1033 if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED) {
1034 normindices++;
1035 }
1036 if (TexturingEnabled == TRUE) {
1037 if (texindices) texindices++;
1038 }
1039 }
1040 glEnd();
1041
1042 } else { // no per_segment binding code below
1043
1044 if (drawAsPoints)
1045 glBegin(GL_POINTS);
1046
1047 while (indices < end) {
1048 if (!drawAsPoints)
1049 glBegin(GL_LINE_STRIP);
1050
1051 i = *indices++;
1052
1053 // Variable used for counting errors and make sure not a bunch of
1054 // errormessages flood the screen.
1055 static uint32_t current_errors = 0;
1056
1057 // This test is for robustness upon buggy data sets
1058 if (i < 0 || i >= numcoords) {
1059 if (current_errors < 1) {
1060 SoDebugError::postWarning("[indexedlineset]::GLRender", "Erroneous coordinate "
1061 "index: %d (Should be within [0, %d]). Aborting "
1062 "rendering. This message will be shown once, but "
1063 "there might be more errors", i, numcoords - 1);
1064 }
1065
1066 current_errors++;
1067 glEnd();
1068 return;
1069 }
1070
1071 if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED ||
1072 (AttributeBinding)MaterialBinding == PER_LINE_INDEXED) {
1073 materials->send(*matindices++, TRUE);
1074 } else if ((AttributeBinding)MaterialBinding == PER_VERTEX ||
1075 (AttributeBinding)MaterialBinding == PER_LINE) {
1076 materials->send(matnr++, TRUE);
1077 }
1078
1079 if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED ||
1080 (AttributeBinding)NormalBinding == PER_LINE_INDEXED) {
1081 currnormal = &normals[*normindices++];
1082 glNormal3fv((const GLfloat*) currnormal);
1083 } else if ((AttributeBinding)NormalBinding == PER_VERTEX ||
1084 (AttributeBinding)NormalBinding == PER_LINE) {
1085 currnormal = normals++;
1086 glNormal3fv((const GLfloat*) currnormal);
1087 }
1088 if (TexturingEnabled == TRUE) {
1089 texcoords->send(texindices ? *texindices++ : texidx++, coords->get3(i), *currnormal);
1090 }
1091
1092 SEND_VERTEX(i);
1093 i = indices < end ? *indices++ : -1;
1094 while (i >= 0) {
1095 // For robustness upon buggy data sets
1096 if (i >= numcoords) {
1097 if (current_errors < 1) {
1098 SoDebugError::postWarning("[indexedlineset]::GLRender", "Erroneous coordinate "
1099 "index: %d (Should be within [0, %d]). Aborting "
1100 "rendering. This message will be shown once, but "
1101 "there might be more errors", i, numcoords - 1);
1102 }
1103 current_errors++;
1104 break;
1105 }
1106
1107 if ((AttributeBinding)MaterialBinding == PER_VERTEX) {
1108 materials->send(matnr++, TRUE);
1109 } else if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED) {
1110 materials->send(*matindices++, TRUE);
1111 }
1112
1113 if ((AttributeBinding)NormalBinding == PER_VERTEX) {
1114 currnormal = normals++;
1115 glNormal3fv((const GLfloat*) currnormal);
1116 } else if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED) {
1117 currnormal = &normals[*normindices++];
1118 glNormal3fv((const GLfloat*) currnormal);
1119 }
1120 if (TexturingEnabled == TRUE) {
1121 texcoords->send(texindices ? *texindices++ : texidx++, coords->get3(i), *currnormal);
1122 }
1123
1124 SEND_VERTEX(i);
1125 i = indices < end ? *indices++ : -1;
1126 }
1127 if (!drawAsPoints)
1128 glEnd(); // end of line strip
1129
1130 if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED) {
1131 matindices++;
1132 }
1133 if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED) {
1134 normindices++;
1135 }
1136 if (TexturingEnabled == TRUE) {
1137 if (texindices) texindices++;
1138 }
1139 }
1140 if (drawAsPoints)
1141 glEnd();
1142 }
1143 }
1144
1145 } } } // namespace
1146
1147 #define SOGL_INDEXEDLINESET_GLRENDER_CALL_FUNC(normalbinding, materialbinding, texturing, args) \
1148 SoGL::IndexedLineSet::GLRender<normalbinding, materialbinding, texturing> args
1149
1150 #define SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG3(normalbinding, materialbinding, texturing, args) \
1151 if (texturing) { \
1152 SOGL_INDEXEDLINESET_GLRENDER_CALL_FUNC(normalbinding, materialbinding, TRUE, args); \
1153 } else { \
1154 SOGL_INDEXEDLINESET_GLRENDER_CALL_FUNC(normalbinding, materialbinding, FALSE, args); \
1155 }
1156
1157 #define SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG2(normalbinding, materialbinding, texturing, args) \
1158 switch (materialbinding) { \
1159 case SoGL::IndexedLineSet::OVERALL: \
1160 SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::IndexedLineSet::OVERALL, texturing, args); \
1161 break; \
1162 case SoGL::IndexedLineSet::PER_SEGMENT: \
1163 SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::IndexedLineSet::PER_SEGMENT, texturing, args); \
1164 break; \
1165 case SoGL::IndexedLineSet::PER_SEGMENT_INDEXED: \
1166 SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::IndexedLineSet::PER_SEGMENT_INDEXED, texturing, args); \
1167 break; \
1168 case SoGL::IndexedLineSet::PER_LINE: \
1169 SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::IndexedLineSet::PER_LINE, texturing, args); \
1170 break; \
1171 case SoGL::IndexedLineSet::PER_LINE_INDEXED: \
1172 SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::IndexedLineSet::PER_LINE_INDEXED, texturing, args); \
1173 break; \
1174 case SoGL::IndexedLineSet::PER_VERTEX: \
1175 SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::IndexedLineSet::PER_VERTEX, texturing, args); \
1176 break; \
1177 case SoGL::IndexedLineSet::PER_VERTEX_INDEXED: \
1178 SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::IndexedLineSet::PER_VERTEX_INDEXED, texturing, args); \
1179 break; \
1180 default: \
1181 assert(!"invalid material binding argument"); \
1182 }
1183
1184 #define SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG1(normalbinding, materialbinding, texturing, args) \
1185 switch (normalbinding) { \
1186 case SoGL::IndexedLineSet::OVERALL: \
1187 SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG2(SoGL::IndexedLineSet::OVERALL, materialbinding, texturing, args); \
1188 break; \
1189 case SoGL::IndexedLineSet::PER_SEGMENT: \
1190 SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG2(SoGL::IndexedLineSet::PER_SEGMENT, materialbinding, texturing, args); \
1191 break; \
1192 case SoGL::IndexedLineSet::PER_SEGMENT_INDEXED: \
1193 SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG2(SoGL::IndexedLineSet::PER_SEGMENT_INDEXED, materialbinding, texturing, args); \
1194 break; \
1195 case SoGL::IndexedLineSet::PER_LINE: \
1196 SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG2(SoGL::IndexedLineSet::PER_LINE, materialbinding, texturing, args); \
1197 break; \
1198 case SoGL::IndexedLineSet::PER_LINE_INDEXED: \
1199 SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG2(SoGL::IndexedLineSet::PER_LINE_INDEXED, materialbinding, texturing, args); \
1200 break; \
1201 case SoGL::IndexedLineSet::PER_VERTEX: \
1202 SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG2(SoGL::IndexedLineSet::PER_VERTEX, materialbinding, texturing, args); \
1203 break; \
1204 case SoGL::IndexedLineSet::PER_VERTEX_INDEXED: \
1205 SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG2(SoGL::IndexedLineSet::PER_VERTEX_INDEXED, materialbinding, texturing, args); \
1206 break; \
1207 default: \
1208 assert(!"invalid normal binding argument"); \
1209 }
1210
1211 #define SOGL_INDEXEDLINESET_GLRENDER(normalbinding, materialbinding, texturing, args) \
1212 SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG1(normalbinding, materialbinding, texturing, args)
1213
1214 void
sogl_render_lineset(const SoGLCoordinateElement * const coords,const int32_t * cindices,int numindices,const SbVec3f * normals,const int32_t * nindices,SoMaterialBundle * const mb,const int32_t * mindices,const SoTextureCoordinateBundle * const tb,const int32_t * tindices,int nbind,int mbind,const int texture,const int drawAsPoints)1215 sogl_render_lineset(const SoGLCoordinateElement * const coords,
1216 const int32_t *cindices,
1217 int numindices,
1218 const SbVec3f *normals,
1219 const int32_t *nindices,
1220 SoMaterialBundle *const mb,
1221 const int32_t *mindices,
1222 const SoTextureCoordinateBundle * const tb,
1223 const int32_t *tindices,
1224 int nbind,
1225 int mbind,
1226 const int texture,
1227 const int drawAsPoints)
1228 {
1229
1230 SOGL_INDEXEDLINESET_GLRENDER(nbind, mbind, texture, (coords,
1231 cindices,
1232 numindices,
1233 normals,
1234 nindices,
1235 mb,
1236 mindices,
1237 tb,
1238 tindices,
1239 drawAsPoints));
1240 }
1241
1242 #undef SOGL_INDEXEDLINESET_GLRENDER_CALL_FUNC
1243 #undef SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG1
1244 #undef SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG2
1245 #undef SOGL_INDEXEDLINESET_GLRENDER_RESOLVE_ARG3
1246 #undef SOGL_INDEXEDLINESET_GLRENDER
1247
1248 #endif // !NO_LINESET_RENDER
1249
1250 // **************************************************************************
1251
1252 #if !defined(NO_FACESET_RENDER)
1253
1254 namespace { namespace SoGL { namespace FaceSet {
1255
1256 enum AttributeBinding {
1257 OVERALL = 0,
1258 PER_FACE = 1,
1259 PER_FACE_INDEXED = 2,
1260 PER_VERTEX = 3,
1261 PER_VERTEX_INDEXED = 4
1262 };
1263
1264 template < int NormalBinding,
1265 int MaterialBinding,
1266 int VertexAttributeBinding >
GLRender(const SoGLCoordinateElement * const vertexlist,const int32_t * vertexindices,int numindices,const SbVec3f * normals,const int32_t * normalindices,SoMaterialBundle * materials,const int32_t * matindices,const SoTextureCoordinateBundle * const texcoords,const int32_t * texindices,SoVertexAttributeBundle * const attribs,const int dotexture,const int doattribs)1267 static void GLRender(const SoGLCoordinateElement * const vertexlist,
1268 const int32_t *vertexindices,
1269 int numindices,
1270 const SbVec3f *normals,
1271 const int32_t *normalindices,
1272 SoMaterialBundle *materials,
1273 const int32_t *matindices,
1274 const SoTextureCoordinateBundle * const texcoords,
1275 const int32_t *texindices,
1276 SoVertexAttributeBundle * const attribs,
1277 const int dotexture,
1278 const int doattribs)
1279 {
1280
1281 // just in case someone forgot
1282 if (matindices == NULL) matindices = vertexindices;
1283 if (normalindices == NULL) normalindices = vertexindices;
1284
1285 int texidx = 0;
1286
1287 const SbVec3f * coords3d = NULL;
1288 const SbVec4f * coords4d = NULL;
1289 const SbBool is3d = vertexlist->is3D();
1290 if (is3d) {
1291 coords3d = vertexlist->getArrayPtr3();
1292 }
1293 else {
1294 coords4d = vertexlist->getArrayPtr4();
1295 }
1296
1297 // This is the same code as in SoGLCoordinateElement::send().
1298 // It is inlined here for speed (~15% speed increase).
1299 #define SEND_VERTEX(_idx_) \
1300 if (is3d) glVertex3fv((const GLfloat*) (coords3d + _idx_)); \
1301 else glVertex4fv((const GLfloat*) (coords4d + _idx_));
1302
1303 int mode = GL_POLYGON; // ...to save a test
1304 int newmode;
1305 const int32_t *viptr = vertexindices;
1306 const int32_t *vistartptr = vertexindices;
1307 const int32_t *viendptr = viptr + numindices;
1308 int32_t v1, v2, v3, v4, v5 = 0; // v5 init unnecessary, but kills a compiler warning.
1309 int numverts = vertexlist->getNum();
1310
1311 SbVec3f dummynormal(0,0,1);
1312 const SbVec3f * currnormal = &dummynormal;
1313 if ((AttributeBinding)NormalBinding == PER_VERTEX ||
1314 (AttributeBinding)NormalBinding == PER_FACE ||
1315 (AttributeBinding)NormalBinding == PER_VERTEX_INDEXED ||
1316 (AttributeBinding)NormalBinding == PER_FACE_INDEXED ||
1317 dotexture) {
1318 if (normals) currnormal = normals;
1319 }
1320
1321 int matnr = 0;
1322 int attribnr = 0;
1323
1324 if (doattribs && (AttributeBinding)VertexAttributeBinding == OVERALL) {
1325 attribs->send(0);
1326 }
1327
1328 while (viptr + 2 < viendptr) {
1329 v1 = *viptr++;
1330 v2 = *viptr++;
1331 v3 = *viptr++;
1332
1333 // Variable used for counting errors and make sure not a
1334 // bunch of errormessages flood the screen.
1335 static uint32_t current_errors = 0;
1336
1337 // This test is for robustness upon buggy data sets
1338 if (v1 < 0 || v2 < 0 || v3 < 0 ||
1339 v1 >= numverts || v2 >= numverts || v3 >= numverts) {
1340
1341 if (current_errors < 1) {
1342 SoDebugError::postWarning("[faceset]::GLRender", "Erroneous polygon detected. "
1343 "Ignoring (offset: %d, [%d %d %d]). Should be within "
1344 " [0, %d] This message will only be shown once, but "
1345 "more errors might be present",
1346 viptr - vistartptr - 3, v1, v2, v3, numverts - 1);
1347 }
1348 current_errors++;
1349 break;
1350 }
1351 v4 = viptr < viendptr ? *viptr++ : -1;
1352 if (v4 < 0) newmode = GL_TRIANGLES;
1353 // This test for numverts is for robustness upon buggy data sets
1354 else if (v4 >= numverts) {
1355 newmode = GL_TRIANGLES;
1356
1357 if (current_errors < 1) {
1358 SoDebugError::postWarning("[faceset]::GLRender", "Erroneous polygon detected. "
1359 "(offset: %d, [%d %d %d %d]). Should be within "
1360 " [0, %d] This message will only be shown once, but "
1361 "more errors might be present",
1362 viptr - vistartptr - 4, v1, v2, v3, v4, numverts - 1);
1363 }
1364 current_errors++;
1365 }
1366 else {
1367 v5 = viptr < viendptr ? *viptr++ : -1;
1368 if (v5 < 0) newmode = GL_QUADS;
1369 // This test for numverts is for robustness upon buggy data sets
1370 else if (v5 >= numverts) {
1371 newmode = GL_QUADS;
1372
1373 if (current_errors < 1) {
1374 SoDebugError::postWarning("[faceset]::GLRender", "Erroneous polygon detected. "
1375 "(offset: %d, [%d %d %d %d %d]). Should be within "
1376 " [0, %d] This message will only be shown once, but "
1377 "more errors might be present",
1378 viptr - vistartptr - 5, v1, v2, v3, v4, v5, numverts - 1);
1379 }
1380 current_errors++;
1381 }
1382 else newmode = GL_POLYGON;
1383 }
1384 if (newmode != mode) {
1385 if (mode != GL_POLYGON) glEnd();
1386 mode = newmode;
1387 glBegin((GLenum) mode);
1388 }
1389 else if (mode == GL_POLYGON) glBegin(GL_POLYGON);
1390
1391 /* vertex 1 *********************************************************/
1392 if ((AttributeBinding)MaterialBinding == PER_VERTEX ||
1393 (AttributeBinding)MaterialBinding == PER_FACE) {
1394 materials->send(matnr++, TRUE);
1395 } else if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED ||
1396 (AttributeBinding)MaterialBinding == PER_FACE_INDEXED) {
1397 materials->send(*matindices++, TRUE);
1398 }
1399
1400 if ((AttributeBinding)NormalBinding == PER_VERTEX ||
1401 (AttributeBinding)NormalBinding == PER_FACE) {
1402 currnormal = normals++;
1403 glNormal3fv((const GLfloat*)currnormal);
1404 } else if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED ||
1405 (AttributeBinding)NormalBinding == PER_FACE_INDEXED) {
1406 currnormal = &normals[*normalindices++];
1407 glNormal3fv((const GLfloat*)currnormal);
1408 }
1409
1410 if ((AttributeBinding)VertexAttributeBinding == PER_VERTEX) {
1411 attribs->send(attribnr++);
1412 } else if ((AttributeBinding)VertexAttributeBinding == PER_VERTEX_INDEXED) {
1413 attribs->send(*vertexindices++);
1414 }
1415
1416 if (dotexture) {
1417 texcoords->send(texindices ? *texindices++ : texidx++,
1418 vertexlist->get3(v1),
1419 *currnormal);
1420 }
1421
1422 SEND_VERTEX(v1);
1423
1424 /* vertex 2 *********************************************************/
1425 if ((AttributeBinding)MaterialBinding == PER_VERTEX) {
1426 materials->send(matnr++, TRUE);
1427 } else if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED) {
1428 materials->send(*matindices++, TRUE);
1429 }
1430
1431 // nvidia color-per-face-bug workaround
1432 if ((AttributeBinding)MaterialBinding == PER_FACE) {
1433 materials->send(matnr-1, TRUE);
1434 } else if ((AttributeBinding)MaterialBinding == PER_FACE_INDEXED) {
1435 materials->send(matindices[-1], TRUE);
1436 }
1437
1438 if ((AttributeBinding)NormalBinding == PER_VERTEX) {
1439 currnormal = normals++;
1440 glNormal3fv((const GLfloat*)currnormal);
1441 } else if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED) {
1442 currnormal = &normals[*normalindices++];
1443 glNormal3fv((const GLfloat*)currnormal);
1444 }
1445
1446 if ((AttributeBinding)VertexAttributeBinding == PER_VERTEX) {
1447 attribs->send(attribnr++);
1448 } else if ((AttributeBinding)VertexAttributeBinding == PER_VERTEX_INDEXED) {
1449 attribs->send(*vertexindices++);
1450 }
1451
1452 if (dotexture) {
1453 texcoords->send(texindices ? *texindices++ : texidx++,
1454 vertexlist->get3(v2),
1455 *currnormal);
1456 }
1457
1458 SEND_VERTEX(v2);
1459
1460 /* vertex 3 *********************************************************/
1461 if ((AttributeBinding)MaterialBinding == PER_VERTEX) {
1462 materials->send(matnr++, TRUE);
1463 } else if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED) {
1464 materials->send(*matindices++, TRUE);
1465 }
1466
1467 // nvidia color-per-face-bug workaround
1468 if ((AttributeBinding)MaterialBinding == PER_FACE) {
1469 materials->send(matnr-1, TRUE);
1470 } else if ((AttributeBinding)MaterialBinding == PER_FACE_INDEXED) {
1471 materials->send(matindices[-1], TRUE);
1472 }
1473
1474 if ((AttributeBinding)NormalBinding == PER_VERTEX) {
1475 currnormal = normals++;
1476 glNormal3fv((const GLfloat*)currnormal);
1477 } else if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED) {
1478 currnormal = &normals[*normalindices++];
1479 glNormal3fv((const GLfloat*)currnormal);
1480 }
1481
1482 if ((AttributeBinding)VertexAttributeBinding == PER_VERTEX) {
1483 attribs->send(attribnr++);
1484 } else if ((AttributeBinding)VertexAttributeBinding == PER_VERTEX_INDEXED) {
1485 attribs->send(*vertexindices++);
1486 }
1487
1488 if (dotexture) {
1489 texcoords->send(texindices ? *texindices++ : texidx++,
1490 vertexlist->get3(v3),
1491 *currnormal);
1492 }
1493
1494 SEND_VERTEX(v3);
1495
1496 if (mode != GL_TRIANGLES) {
1497 /* vertex 4 (quad or polygon)**************************************/
1498 if ((AttributeBinding)MaterialBinding == PER_VERTEX) {
1499 materials->send(matnr++, TRUE);
1500 } else if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED) {
1501 materials->send(*matindices++, TRUE);
1502 }
1503
1504 // nvidia color-per-face-bug workaround
1505 if ((AttributeBinding)MaterialBinding == PER_FACE) {
1506 materials->send(matnr-1, TRUE);
1507 } else if ((AttributeBinding)MaterialBinding == PER_FACE_INDEXED) {
1508 materials->send(matindices[-1], TRUE);
1509 }
1510
1511 if ((AttributeBinding)NormalBinding == PER_VERTEX) {
1512 currnormal = normals++;
1513 glNormal3fv((const GLfloat*)currnormal);
1514 } else if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED) {
1515 currnormal = &normals[*normalindices++];
1516 glNormal3fv((const GLfloat*)currnormal);
1517 }
1518
1519 if (dotexture) {
1520 texcoords->send(texindices ? *texindices++ : texidx++,
1521 vertexlist->get3(v4),
1522 *currnormal);
1523 }
1524
1525 if ((AttributeBinding)VertexAttributeBinding == PER_VERTEX) {
1526 attribs->send(attribnr++);
1527 }
1528 else if ((AttributeBinding)VertexAttributeBinding == PER_VERTEX_INDEXED) {
1529 attribs->send(*vertexindices++);
1530 }
1531 SEND_VERTEX(v4);
1532
1533 if (mode == GL_POLYGON) {
1534 /* vertex 5 (polygon) ********************************************/
1535 if ((AttributeBinding)MaterialBinding == PER_VERTEX) {
1536 materials->send(matnr++, TRUE);
1537 } else if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED) {
1538 materials->send(*matindices++, TRUE);
1539 }
1540
1541 // nvidia color-per-face-bug workaround
1542 if ((AttributeBinding)MaterialBinding == PER_FACE) {
1543 materials->send(matnr-1, TRUE);
1544 } else if ((AttributeBinding)MaterialBinding == PER_FACE_INDEXED) {
1545 materials->send(matindices[-1], TRUE);
1546 }
1547
1548 if ((AttributeBinding)NormalBinding == PER_VERTEX) {
1549 currnormal = normals++;
1550 glNormal3fv((const GLfloat*)currnormal);
1551 } else if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED) {
1552 currnormal = &normals[*normalindices++];
1553 glNormal3fv((const GLfloat*)currnormal);
1554 }
1555
1556 if ((AttributeBinding)VertexAttributeBinding == PER_VERTEX) {
1557 attribs->send(attribnr++);
1558 } else if ((AttributeBinding)VertexAttributeBinding == PER_VERTEX_INDEXED) {
1559 attribs->send(*vertexindices++);
1560 }
1561
1562 if (dotexture) {
1563 texcoords->send(texindices ? *texindices++ : texidx++,
1564 vertexlist->get3(v5),
1565 *currnormal);
1566
1567 }
1568
1569 SEND_VERTEX(v5);
1570
1571 v1 = viptr < viendptr ? *viptr++ : -1;
1572 while (v1 >= 0) {
1573 // For robustness upon buggy data sets
1574 if (v1 >= numverts) {
1575 if (current_errors < 1) {
1576 SoDebugError::postWarning("[faceset]::GLRender", "Erroneous polygon detected. "
1577 "(offset: %d, [... %d]). Should be within "
1578 "[0, %d] This message will only be shown once, but "
1579 "more errors might be present",
1580 viptr - vistartptr - 1, v1, numverts - 1);
1581 }
1582 current_errors++;
1583 break;
1584 }
1585
1586 /* vertex 6-n (polygon) *****************************************/
1587 if ((AttributeBinding)MaterialBinding == PER_VERTEX) {
1588 materials->send(matnr++, TRUE);
1589 } else if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED) {
1590 materials->send(*matindices++, TRUE);
1591 }
1592
1593 // nvidia color-per-face-bug workaround
1594 if ((AttributeBinding)MaterialBinding == PER_FACE) {
1595 materials->send(matnr-1, TRUE);
1596 } else if ((AttributeBinding)MaterialBinding == PER_FACE_INDEXED) {
1597 materials->send(matindices[-1], TRUE);
1598 }
1599
1600 if ((AttributeBinding)NormalBinding == PER_VERTEX) {
1601 currnormal = normals++;
1602 glNormal3fv((const GLfloat*)currnormal);
1603 } else if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED) {
1604 currnormal = &normals[*normalindices++];
1605 glNormal3fv((const GLfloat*)currnormal);
1606 }
1607
1608 if (dotexture) {
1609 texcoords->send(texindices ? *texindices++ : texidx++,
1610 vertexlist->get3(v1),
1611 *currnormal);
1612 }
1613
1614 if ((AttributeBinding)VertexAttributeBinding == PER_VERTEX) {
1615 attribs->send(attribnr++);
1616 } else if ((AttributeBinding)VertexAttributeBinding == PER_VERTEX_INDEXED) {
1617 attribs->send(*vertexindices++);
1618 }
1619 SEND_VERTEX(v1);
1620
1621 v1 = viptr < viendptr ? *viptr++ : -1;
1622 }
1623 glEnd(); /* draw polygon */
1624 }
1625 }
1626
1627 if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED) {
1628 matindices++;
1629 }
1630 if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED) {
1631 normalindices++;
1632 }
1633 if ((AttributeBinding)VertexAttributeBinding == PER_VERTEX_INDEXED) {
1634 vertexindices++;
1635 }
1636
1637 if (dotexture) {
1638 if (texindices) texindices++;
1639 }
1640 }
1641 // check if triangle or quad
1642 if (mode != GL_POLYGON) glEnd();
1643 }
1644
1645 } } } // namespace
1646
1647 #define SOGL_FACESET_GLRENDER_CALL_FUNC(normalbinding, materialbinding, vertexattributebinding, args) \
1648 SoGL::FaceSet::GLRender<normalbinding, materialbinding, vertexattributebinding> args
1649
1650 #define SOGL_FACESET_GLRENDER_RESOLVE_ARG3(normalbinding, materialbinding, vertexattributebinding, args) \
1651 switch (vertexattributebinding) { \
1652 case SoGL::FaceSet::OVERALL: \
1653 SOGL_FACESET_GLRENDER_CALL_FUNC(normalbinding, materialbinding, SoGL::FaceSet::OVERALL, args); \
1654 break; \
1655 case SoGL::FaceSet::PER_FACE: \
1656 SOGL_FACESET_GLRENDER_CALL_FUNC(normalbinding, materialbinding, SoGL::FaceSet::OVERALL, args); \
1657 break; \
1658 case SoGL::FaceSet::PER_FACE_INDEXED: \
1659 SOGL_FACESET_GLRENDER_CALL_FUNC(normalbinding, materialbinding, SoGL::FaceSet::OVERALL, args); \
1660 break; \
1661 case SoGL::FaceSet::PER_VERTEX: \
1662 SOGL_FACESET_GLRENDER_CALL_FUNC(normalbinding, materialbinding, SoGL::FaceSet::PER_VERTEX, args); \
1663 break; \
1664 case SoGL::FaceSet::PER_VERTEX_INDEXED: \
1665 SOGL_FACESET_GLRENDER_CALL_FUNC(normalbinding, materialbinding, SoGL::FaceSet::PER_VERTEX_INDEXED, args); \
1666 break; \
1667 default: \
1668 assert(!"invalid vertex attribute binding argument"); \
1669 }
1670
1671 #define SOGL_FACESET_GLRENDER_RESOLVE_ARG2(normalbinding, materialbinding, vertexattributebinding, args) \
1672 switch (materialbinding) { \
1673 case SoGL::FaceSet::OVERALL: \
1674 SOGL_FACESET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::FaceSet::OVERALL, vertexattributebinding, args); \
1675 break; \
1676 case SoGL::FaceSet::PER_FACE: \
1677 SOGL_FACESET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::FaceSet::PER_FACE, vertexattributebinding, args); \
1678 break; \
1679 case SoGL::FaceSet::PER_FACE_INDEXED: \
1680 SOGL_FACESET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::FaceSet::PER_FACE_INDEXED, vertexattributebinding, args); \
1681 break; \
1682 case SoGL::FaceSet::PER_VERTEX: \
1683 SOGL_FACESET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::FaceSet::PER_VERTEX, vertexattributebinding, args); \
1684 break; \
1685 case SoGL::FaceSet::PER_VERTEX_INDEXED: \
1686 SOGL_FACESET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::FaceSet::PER_VERTEX_INDEXED, vertexattributebinding, args); \
1687 break; \
1688 default: \
1689 assert(!"invalid material binding argument"); \
1690 }
1691
1692 #define SOGL_FACESET_GLRENDER_RESOLVE_ARG1(normalbinding, materialbinding, vertexattributebinding, args) \
1693 switch (normalbinding) { \
1694 case SoGL::FaceSet::OVERALL: \
1695 SOGL_FACESET_GLRENDER_RESOLVE_ARG2(SoGL::FaceSet::OVERALL, materialbinding, vertexattributebinding, args); \
1696 break; \
1697 case SoGL::FaceSet::PER_FACE: \
1698 SOGL_FACESET_GLRENDER_RESOLVE_ARG2(SoGL::FaceSet::PER_FACE, materialbinding, vertexattributebinding, args); \
1699 break; \
1700 case SoGL::FaceSet::PER_FACE_INDEXED: \
1701 SOGL_FACESET_GLRENDER_RESOLVE_ARG2(SoGL::FaceSet::PER_FACE_INDEXED, materialbinding, vertexattributebinding, args); \
1702 break; \
1703 case SoGL::FaceSet::PER_VERTEX: \
1704 SOGL_FACESET_GLRENDER_RESOLVE_ARG2(SoGL::FaceSet::PER_VERTEX, materialbinding, vertexattributebinding, args); \
1705 break; \
1706 case SoGL::FaceSet::PER_VERTEX_INDEXED: \
1707 SOGL_FACESET_GLRENDER_RESOLVE_ARG2(SoGL::FaceSet::PER_VERTEX_INDEXED, materialbinding, vertexattributebinding, args); \
1708 break; \
1709 default: \
1710 assert(!"invalid normal binding argument"); \
1711 }
1712
1713 #define SOGL_FACESET_GLRENDER(normalbinding, materialbinding, vertexattributebinding, args) \
1714 SOGL_FACESET_GLRENDER_RESOLVE_ARG1(normalbinding, materialbinding, vertexattributebinding, args)
1715
1716
1717 void
sogl_render_faceset(const SoGLCoordinateElement * const vertexlist,const int32_t * vertexindices,int num_vertexindices,const SbVec3f * normals,const int32_t * normindices,SoMaterialBundle * const materials,const int32_t * matindices,SoTextureCoordinateBundle * const texcoords,const int32_t * texindices,SoVertexAttributeBundle * const attribs,const int nbind,const int mbind,const int attribbind,const int dotexture,const int doattribs)1718 sogl_render_faceset(const SoGLCoordinateElement * const vertexlist,
1719 const int32_t *vertexindices,
1720 int num_vertexindices,
1721 const SbVec3f *normals,
1722 const int32_t *normindices,
1723 SoMaterialBundle *const materials,
1724 const int32_t *matindices,
1725 SoTextureCoordinateBundle * const texcoords,
1726 const int32_t *texindices,
1727 SoVertexAttributeBundle * const attribs,
1728 const int nbind,
1729 const int mbind,
1730 const int attribbind,
1731 const int dotexture,
1732 const int doattribs)
1733 {
1734 SOGL_FACESET_GLRENDER(nbind, mbind, attribbind, (vertexlist,
1735 vertexindices,
1736 num_vertexindices,
1737 normals,
1738 normindices,
1739 materials,
1740 matindices,
1741 texcoords,
1742 texindices,
1743 attribs,
1744 dotexture,
1745 doattribs));
1746 }
1747
1748 #undef SOGL_FACESET_GLRENDER
1749 #undef SOGL_FACESET_GLRENDER_RESOLVE_ARG1
1750 #undef SOGL_FACESET_GLRENDER_RESOLVE_ARG2
1751 #undef SOGL_FACESET_GLRENDER_RESOLVE_ARG3
1752 #undef SOGL_FACESET_GLRENDER_RESOLVE_ARG4
1753 #undef SOGL_FACESET_GLRENDER_CALL_FUNC
1754
1755 #endif // !NO_FACESET_RENDER
1756
1757 // **************************************************************************
1758
1759 //typedef void sogl_render_faceset_func(const SoGLCoordinateElement * const coords,
1760 // const int32_t *vertexindices,
1761 // int num_vertexindices,
1762 // const SbVec3f *normals,
1763 // const int32_t *normindices,
1764 // SoMaterialBundle *materials,
1765 // const int32_t *matindices,
1766 // const SoTextureCoordinateBundle * const texcoords,
1767 // const int32_t *texindices);
1768
1769 #if !defined(NO_TRISTRIPSET_RENDER)
1770
1771 namespace { namespace SoGL { namespace TriStripSet {
1772
1773 enum AttributeBinding {
1774 OVERALL = 0,
1775 PER_STRIP = 1,
1776 PER_STRIP_INDEXED = 2,
1777 PER_TRIANGLE = 3,
1778 PER_TRIANGLE_INDEXED = 4,
1779 PER_VERTEX = 5,
1780 PER_VERTEX_INDEXED = 6
1781 };
1782
1783 template < int NormalBinding,
1784 int MaterialBinding,
1785 int TexturingEnabled >
GLRender(const SoGLCoordinateElement * const vertexlist,const int32_t * vertexindices,int numindices,const SbVec3f * normals,const int32_t * normalindices,SoMaterialBundle * materials,const int32_t * matindices,const SoTextureCoordinateBundle * const texcoords,const int32_t * texindices)1786 static void GLRender(const SoGLCoordinateElement * const vertexlist,
1787 const int32_t *vertexindices,
1788 int numindices,
1789 const SbVec3f *normals,
1790 const int32_t *normalindices,
1791 SoMaterialBundle *materials,
1792 const int32_t *matindices,
1793 const SoTextureCoordinateBundle * const texcoords,
1794 const int32_t *texindices)
1795 {
1796
1797 // just in case someone forgot...
1798 if (matindices == NULL) matindices = vertexindices;
1799 if (normalindices == NULL) normalindices = vertexindices;
1800
1801 int texidx = 0;
1802 const int32_t *viptr = vertexindices;
1803 const int32_t *vistartptr = vertexindices;
1804 const int32_t *viendptr = viptr + numindices;
1805 int32_t v1, v2, v3;
1806 int numverts = vertexlist->getNum();
1807
1808 const SbVec3f * coords3d = NULL;
1809 const SbVec4f * coords4d = NULL;
1810 const SbBool is3d = vertexlist->is3D();
1811 if (is3d) {
1812 coords3d = vertexlist->getArrayPtr3();
1813 }
1814 else {
1815 coords4d = vertexlist->getArrayPtr4();
1816 }
1817
1818 // This is the same code as in SoGLCoordinateElement::send().
1819 // It is inlined here for speed (~15% speed increase).
1820 #define SEND_VERTEX_TRISTRIP(_idx_) \
1821 if (is3d) glVertex3fv((const GLfloat*) (coords3d + _idx_)); \
1822 else glVertex4fv((const GLfloat*) (coords4d + _idx_));
1823
1824 if ((AttributeBinding)NormalBinding == PER_VERTEX ||
1825 (AttributeBinding)NormalBinding == PER_TRIANGLE ||
1826 (AttributeBinding)NormalBinding == PER_STRIP ||
1827 (AttributeBinding)NormalBinding == PER_VERTEX_INDEXED ||
1828 (AttributeBinding)NormalBinding == PER_TRIANGLE_INDEXED ||
1829 (AttributeBinding)NormalBinding == PER_STRIP_INDEXED) {
1830 assert(normals && "Aborting rendering of tristrip; got NULL normals");
1831 }
1832
1833 SbVec3f dummynormal(0.0f, 0.0f, 1.0f);
1834 const SbVec3f *currnormal = &dummynormal;
1835
1836 if ((AttributeBinding)NormalBinding == PER_VERTEX ||
1837 (AttributeBinding)NormalBinding == PER_TRIANGLE ||
1838 (AttributeBinding)NormalBinding == PER_STRIP ||
1839 (AttributeBinding)NormalBinding == PER_VERTEX_INDEXED ||
1840 (AttributeBinding)NormalBinding == PER_TRIANGLE_INDEXED ||
1841 (AttributeBinding)NormalBinding == PER_STRIP_INDEXED ||
1842 TexturingEnabled == TRUE) {
1843 if (normals) currnormal = normals;
1844 }
1845
1846 int matnr = 0;
1847
1848 while (viptr + 2 < viendptr) {
1849 v1 = *viptr++;
1850 v2 = *viptr++;
1851 v3 = *viptr++;
1852
1853 // This should be here to prevent illegal polygons from being rendered
1854 if (v1 < 0 || v2 < 0 || v3 < 0 ||
1855 v1 >= numverts || v2 >= numverts || v3 >= numverts) {
1856
1857 static uint32_t current_errors = 0;
1858 if (current_errors < 1) {
1859 SoDebugError::postWarning("[tristrip]::GLRender", "Erroneous polygon detected. "
1860 "Ignoring (offset: %d, [%d %d %d]). Should be within "
1861 " [0, %d] This message will only be shown once, but "
1862 "more errors may be present",
1863 viptr - vistartptr - 3, v1, v2, v3, numverts - 1);
1864 }
1865
1866 current_errors++;
1867 break;
1868 }
1869
1870 glBegin(GL_TRIANGLE_STRIP);
1871
1872 /* vertex 1 *********************************************************/
1873 if ((AttributeBinding)MaterialBinding == PER_VERTEX ||
1874 (AttributeBinding)MaterialBinding == PER_STRIP ||
1875 (AttributeBinding)MaterialBinding == PER_TRIANGLE) {
1876 materials->send(matnr++, TRUE);
1877 } else if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED ||
1878 (AttributeBinding)MaterialBinding == PER_STRIP_INDEXED ||
1879 (AttributeBinding)MaterialBinding == PER_TRIANGLE_INDEXED) {
1880 materials->send(*matindices++, TRUE);
1881 }
1882 if ((AttributeBinding)NormalBinding == PER_VERTEX ||
1883 (AttributeBinding)NormalBinding == PER_STRIP ||
1884 (AttributeBinding)NormalBinding == PER_TRIANGLE) {
1885 currnormal = normals++;
1886 glNormal3fv((const GLfloat*)currnormal);
1887 } else if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED ||
1888 (AttributeBinding)NormalBinding == PER_TRIANGLE_INDEXED ||
1889 (AttributeBinding)NormalBinding == PER_STRIP_INDEXED) {
1890 currnormal = &normals[*normalindices++];
1891 glNormal3fv((const GLfloat*)currnormal);
1892 }
1893 if (TexturingEnabled == TRUE) {
1894 texcoords->send(texindices ? *texindices++ : texidx++,
1895 vertexlist->get3(v1),
1896 *currnormal);
1897 }
1898 SEND_VERTEX_TRISTRIP(v1);
1899
1900 /* vertex 2 *********************************************************/
1901 if ((AttributeBinding)MaterialBinding == PER_VERTEX) {
1902 materials->send(matnr++, TRUE);
1903 } else if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED) {
1904 materials->send(*matindices++, TRUE);
1905 }
1906
1907 // needed for nvidia color-per-face-bug workaround
1908 if ((AttributeBinding)MaterialBinding == PER_TRIANGLE ||
1909 (AttributeBinding)MaterialBinding == PER_STRIP) {
1910 materials->send(matnr-1, TRUE);
1911 } else if ((AttributeBinding)MaterialBinding == PER_TRIANGLE_INDEXED ||
1912 (AttributeBinding)MaterialBinding == PER_STRIP_INDEXED) {
1913 materials->send(matindices[-1], TRUE);
1914 }
1915 // end of nvidia workaround
1916
1917 if ((AttributeBinding)NormalBinding == PER_VERTEX) {
1918 currnormal = normals++;
1919 glNormal3fv((const GLfloat*)currnormal);
1920 } else if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED) {
1921 currnormal = &normals[*normalindices++];
1922 glNormal3fv((const GLfloat*)currnormal);
1923 }
1924 if (TexturingEnabled == TRUE) {
1925 texcoords->send(texindices ? *texindices++ : texidx++,
1926 vertexlist->get3(v2),
1927 *currnormal);
1928 }
1929 SEND_VERTEX_TRISTRIP(v2);
1930
1931 /* vertex 3 *********************************************************/
1932 if ((AttributeBinding)MaterialBinding == PER_VERTEX) {
1933 materials->send(matnr++, TRUE);
1934 } else if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED) {
1935 materials->send(*matindices++, TRUE);
1936 }
1937
1938 // needed for nvidia color-per-face-bug workaround
1939 if ((AttributeBinding)MaterialBinding == PER_STRIP ||
1940 (AttributeBinding)MaterialBinding == PER_TRIANGLE) {
1941 materials->send(matnr-1, TRUE);
1942 } else if ((AttributeBinding)MaterialBinding == PER_TRIANGLE_INDEXED ||
1943 (AttributeBinding)MaterialBinding == PER_STRIP_INDEXED) {
1944 materials->send(matindices[-1], TRUE);
1945 }
1946 // end of nvidia workaround
1947
1948 if ((AttributeBinding)NormalBinding == PER_VERTEX) {
1949 currnormal = normals++;
1950 glNormal3fv((const GLfloat*)currnormal);
1951 } else if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED) {
1952 currnormal = &normals[*normalindices++];
1953 glNormal3fv((const GLfloat*)currnormal);
1954 }
1955 if (TexturingEnabled == TRUE) {
1956 texcoords->send(texindices ? *texindices++ : texidx++,
1957 vertexlist->get3(v3),
1958 *currnormal);
1959 }
1960 SEND_VERTEX_TRISTRIP(v3);
1961
1962 v1 = viptr < viendptr ? *viptr++ : -1;
1963 while (v1 >= 0) {
1964 if ((AttributeBinding)MaterialBinding == PER_VERTEX ||
1965 (AttributeBinding)MaterialBinding == PER_TRIANGLE) {
1966 materials->send(matnr++, TRUE);
1967 } else if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED ||
1968 (AttributeBinding)MaterialBinding == PER_TRIANGLE_INDEXED) {
1969 materials->send(*matindices++, TRUE);
1970 }
1971
1972 // needed for nvidia color-per-face-bug workaround
1973 if ((AttributeBinding)MaterialBinding == PER_STRIP) {
1974 materials->send(matnr-1, TRUE);
1975 } else if ((AttributeBinding)MaterialBinding == PER_STRIP_INDEXED) {
1976 materials->send(matindices[-1], TRUE);
1977 }
1978 // end of nvidia workaround
1979
1980 if ((AttributeBinding)NormalBinding == PER_VERTEX ||
1981 (AttributeBinding)NormalBinding == PER_TRIANGLE) {
1982 currnormal = normals++;
1983 glNormal3fv((const GLfloat*)currnormal);
1984 } else if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED ||
1985 (AttributeBinding)NormalBinding == PER_TRIANGLE_INDEXED) {
1986 currnormal = &normals[*normalindices++];
1987 glNormal3fv((const GLfloat*)currnormal);
1988 }
1989 if (TexturingEnabled == TRUE) {
1990 texcoords->send(texindices ? *texindices++ : texidx++,
1991 vertexlist->get3(v1),
1992 *currnormal);
1993 }
1994
1995 SEND_VERTEX_TRISTRIP(v1);
1996 v1 = viptr < viendptr ? *viptr++ : -1;
1997 }
1998 glEnd(); // end of tristrip
1999
2000 if ((AttributeBinding)MaterialBinding == PER_VERTEX_INDEXED) {
2001 matindices++;
2002 }
2003 if ((AttributeBinding)NormalBinding == PER_VERTEX_INDEXED) {
2004 normalindices++;
2005 }
2006 if (TexturingEnabled == TRUE) {
2007 if (texindices) texindices++;
2008 }
2009 }
2010 }
2011
2012 } } } // namespace
2013
2014 #define SOGL_TRISTRIPSET_GLRENDER_CALL_FUNC(normalbinding, materialbinding, texturing, args) \
2015 SoGL::TriStripSet::GLRender<normalbinding, materialbinding, texturing> args
2016
2017 #define SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG3(normalbinding, materialbinding, texturing, args) \
2018 if (texturing) { \
2019 SOGL_TRISTRIPSET_GLRENDER_CALL_FUNC(normalbinding, materialbinding, TRUE, args); \
2020 } else { \
2021 SOGL_TRISTRIPSET_GLRENDER_CALL_FUNC(normalbinding, materialbinding, FALSE, args); \
2022 }
2023
2024 #define SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG2(normalbinding, materialbinding, texturing, args) \
2025 switch (materialbinding) { \
2026 case SoGL::TriStripSet::OVERALL: \
2027 SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::TriStripSet::OVERALL, texturing, args); \
2028 break; \
2029 case SoGL::TriStripSet::PER_STRIP: \
2030 SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::TriStripSet::PER_STRIP, texturing, args); \
2031 break; \
2032 case SoGL::TriStripSet::PER_STRIP_INDEXED: \
2033 SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::TriStripSet::PER_STRIP_INDEXED, texturing, args); \
2034 break; \
2035 case SoGL::TriStripSet::PER_TRIANGLE: \
2036 SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::TriStripSet::PER_TRIANGLE, texturing, args); \
2037 break; \
2038 case SoGL::TriStripSet::PER_TRIANGLE_INDEXED: \
2039 SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::TriStripSet::PER_TRIANGLE_INDEXED, texturing, args); \
2040 break; \
2041 case SoGL::IndexedLineSet::PER_VERTEX: \
2042 SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::TriStripSet::PER_VERTEX, texturing, args); \
2043 break; \
2044 case SoGL::IndexedLineSet::PER_VERTEX_INDEXED: \
2045 SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG3(normalbinding, SoGL::TriStripSet::PER_VERTEX_INDEXED, texturing, args); \
2046 break; \
2047 default: \
2048 assert(!"invalid material binding argument"); \
2049 }
2050
2051 #define SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG1(normalbinding, materialbinding, texturing, args) \
2052 switch (normalbinding) { \
2053 case SoGL::TriStripSet::OVERALL: \
2054 SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG2(SoGL::TriStripSet::OVERALL, materialbinding, texturing, args); \
2055 break; \
2056 case SoGL::TriStripSet::PER_STRIP: \
2057 SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG2(SoGL::TriStripSet::PER_STRIP, materialbinding, texturing, args); \
2058 break; \
2059 case SoGL::TriStripSet::PER_STRIP_INDEXED: \
2060 SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG2(SoGL::TriStripSet::PER_STRIP_INDEXED, materialbinding, texturing, args); \
2061 break; \
2062 case SoGL::TriStripSet::PER_TRIANGLE: \
2063 SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG2(SoGL::TriStripSet::PER_TRIANGLE, materialbinding, texturing, args); \
2064 break; \
2065 case SoGL::TriStripSet::PER_TRIANGLE_INDEXED: \
2066 SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG2(SoGL::TriStripSet::PER_TRIANGLE_INDEXED, materialbinding, texturing, args); \
2067 break; \
2068 case SoGL::TriStripSet::PER_VERTEX: \
2069 SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG2(SoGL::TriStripSet::PER_VERTEX, materialbinding, texturing, args); \
2070 break; \
2071 case SoGL::TriStripSet::PER_VERTEX_INDEXED: \
2072 SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG2(SoGL::TriStripSet::PER_VERTEX_INDEXED, materialbinding, texturing, args); \
2073 break; \
2074 default: \
2075 assert(!"invalid normal binding argument"); \
2076 }
2077
2078 #define SOGL_TRISTRIPSET_GLRENDER(normalbinding, materialbinding, texturing, args) \
2079 SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG1(normalbinding, materialbinding, texturing, args)
2080
2081 void
sogl_render_tristrip(const SoGLCoordinateElement * const vertexlist,const int32_t * vertexindices,int num_vertexindices,const SbVec3f * normals,const int32_t * normindices,SoMaterialBundle * const materials,const int32_t * matindices,const SoTextureCoordinateBundle * const texcoords,const int32_t * texindices,const int nbind,const int mbind,const int texture)2082 sogl_render_tristrip(const SoGLCoordinateElement * const vertexlist,
2083 const int32_t *vertexindices,
2084 int num_vertexindices,
2085 const SbVec3f *normals,
2086 const int32_t *normindices,
2087 SoMaterialBundle *const materials,
2088 const int32_t *matindices,
2089 const SoTextureCoordinateBundle * const texcoords,
2090 const int32_t *texindices,
2091 const int nbind,
2092 const int mbind,
2093 const int texture)
2094 {
2095 SOGL_TRISTRIPSET_GLRENDER(nbind, mbind, texture, (vertexlist,
2096 vertexindices,
2097 num_vertexindices,
2098 normals,
2099 normindices,
2100 materials,
2101 matindices,
2102 texcoords,
2103 texindices));
2104 }
2105
2106 #undef SOGL_TRISTRIPSET_GLRENDER_CALL_FUNC
2107 #undef SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG1
2108 #undef SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG2
2109 #undef SOGL_TRISTRIPSET_GLRENDER_RESOLVE_ARG3
2110 #undef SOGL_TRISTRIPSET_GLRENDER
2111
2112 #endif // !NO_TRISTRIPSET_RENDER
2113
2114
2115 // PointSet rendering
2116 // here we include the 8 variations directly...
2117
2118 static void
sogl_render_pointset_m0n0t0(const SoGLCoordinateElement * coords,const SbVec3f * COIN_UNUSED_ARG (normals),SoMaterialBundle * COIN_UNUSED_ARG (mb),const SoTextureCoordinateBundle * COIN_UNUSED_ARG (tb),int32_t numpts,int32_t idx)2119 sogl_render_pointset_m0n0t0(const SoGLCoordinateElement * coords,
2120 const SbVec3f * COIN_UNUSED_ARG(normals),
2121 SoMaterialBundle * COIN_UNUSED_ARG(mb),
2122 const SoTextureCoordinateBundle * COIN_UNUSED_ARG(tb),
2123 int32_t numpts,
2124 int32_t idx)
2125 {
2126 int i;
2127 const int unroll = numpts >> 2;
2128 const int rest = numpts & 3;
2129
2130 // manually unroll this common loop
2131
2132 glBegin(GL_POINTS);
2133 for (i = 0; i < unroll; i++) {
2134 coords->send(idx++);
2135 coords->send(idx++);
2136 coords->send(idx++);
2137 coords->send(idx++);
2138 }
2139 for (i = 0; i < rest; i++) {
2140 coords->send(idx++);
2141 }
2142 glEnd();
2143 }
2144
2145 static void
sogl_render_pointset_m0n0t1(const SoGLCoordinateElement * coords,const SbVec3f * COIN_UNUSED_ARG (normals),SoMaterialBundle * COIN_UNUSED_ARG (mb),const SoTextureCoordinateBundle * tb,int32_t numpts,int32_t idx)2146 sogl_render_pointset_m0n0t1(const SoGLCoordinateElement * coords,
2147 const SbVec3f * COIN_UNUSED_ARG(normals),
2148 SoMaterialBundle * COIN_UNUSED_ARG(mb),
2149 const SoTextureCoordinateBundle * tb,
2150 int32_t numpts,
2151 int32_t idx)
2152 {
2153 int texnr = 0;
2154 const SbVec3f currnormal(0.0f,0.0f,1.0f);
2155
2156 glBegin(GL_POINTS);
2157 for (int i = 0; i < numpts; i++) {
2158 tb->send(texnr++, coords->get3(idx), currnormal);
2159 coords->send(idx++);
2160 }
2161 glEnd();
2162 }
2163
2164 static void
sogl_render_pointset_m0n1t0(const SoGLCoordinateElement * coords,const SbVec3f * normals,SoMaterialBundle * COIN_UNUSED_ARG (mb),const SoTextureCoordinateBundle * COIN_UNUSED_ARG (tb),int32_t numpts,int32_t idx)2165 sogl_render_pointset_m0n1t0(const SoGLCoordinateElement * coords,
2166 const SbVec3f * normals,
2167 SoMaterialBundle * COIN_UNUSED_ARG(mb),
2168 const SoTextureCoordinateBundle * COIN_UNUSED_ARG(tb),
2169 int32_t numpts,
2170 int32_t idx)
2171 {
2172 glBegin(GL_POINTS);
2173 for (int i = 0; i < numpts; i++) {
2174 glNormal3fv((const GLfloat*)normals++);
2175 coords->send(idx++);
2176 }
2177 glEnd();
2178 }
2179
2180 static void
sogl_render_pointset_m0n1t1(const SoGLCoordinateElement * coords,const SbVec3f * normals,SoMaterialBundle * COIN_UNUSED_ARG (mb),const SoTextureCoordinateBundle * tb,int32_t numpts,int32_t idx)2181 sogl_render_pointset_m0n1t1(const SoGLCoordinateElement * coords,
2182 const SbVec3f * normals,
2183 SoMaterialBundle * COIN_UNUSED_ARG(mb),
2184 const SoTextureCoordinateBundle * tb,
2185 int32_t numpts,
2186 int32_t idx)
2187 {
2188 int texnr = 0;
2189 const SbVec3f currnormal(0.0f,0.0f,1.0f);
2190
2191 glBegin(GL_POINTS);
2192 for (int i = 0; i < numpts; i++) {
2193 glNormal3fv((const GLfloat*)normals++);
2194 tb->send(texnr++, coords->get3(idx), currnormal);
2195 coords->send(idx++);
2196 }
2197 glEnd();
2198 }
2199
2200 static void
sogl_render_pointset_m1n0t0(const SoGLCoordinateElement * coords,const SbVec3f * COIN_UNUSED_ARG (normals),SoMaterialBundle * mb,const SoTextureCoordinateBundle * COIN_UNUSED_ARG (tb),int32_t numpts,int32_t idx)2201 sogl_render_pointset_m1n0t0(const SoGLCoordinateElement * coords,
2202 const SbVec3f * COIN_UNUSED_ARG(normals),
2203 SoMaterialBundle * mb,
2204 const SoTextureCoordinateBundle * COIN_UNUSED_ARG(tb),
2205 int32_t numpts,
2206 int32_t idx)
2207 {
2208 int i;
2209 int matnr = 0;
2210 const int unroll = numpts >> 2;
2211 const int rest = numpts & 3;
2212
2213 // manually unroll this common loop
2214
2215 glBegin(GL_POINTS);
2216 for (i = 0; i < unroll; i++) {
2217 mb->send(matnr++, TRUE);
2218 coords->send(idx++);
2219 mb->send(matnr++, TRUE);
2220 coords->send(idx++);
2221 mb->send(matnr++, TRUE);
2222 coords->send(idx++);
2223 mb->send(matnr++, TRUE);
2224 coords->send(idx++);
2225 }
2226 for (i = 0; i < rest; i++) {
2227 mb->send(matnr++, TRUE);
2228 coords->send(idx++);
2229 }
2230 glEnd();
2231 }
2232
2233 static void
sogl_render_pointset_m1n0t1(const SoGLCoordinateElement * coords,const SbVec3f * COIN_UNUSED_ARG (normals),SoMaterialBundle * mb,const SoTextureCoordinateBundle * tb,int32_t numpts,int32_t idx)2234 sogl_render_pointset_m1n0t1(const SoGLCoordinateElement * coords,
2235 const SbVec3f * COIN_UNUSED_ARG(normals),
2236 SoMaterialBundle * mb,
2237 const SoTextureCoordinateBundle * tb,
2238 int32_t numpts,
2239 int32_t idx)
2240 {
2241 int matnr = 0;
2242 int texnr = 0;
2243 const SbVec3f currnormal(0.0f,0.0f,1.0f);
2244
2245 glBegin(GL_POINTS);
2246 for (int i = 0; i < numpts; i++) {
2247 mb->send(matnr++, TRUE);
2248 tb->send(texnr++, coords->get3(idx), currnormal);
2249 coords->send(idx++);
2250 }
2251 glEnd();
2252 }
2253
2254 static void
sogl_render_pointset_m1n1t0(const SoGLCoordinateElement * coords,const SbVec3f * normals,SoMaterialBundle * mb,const SoTextureCoordinateBundle * COIN_UNUSED_ARG (tb),int32_t numpts,int32_t idx)2255 sogl_render_pointset_m1n1t0(const SoGLCoordinateElement * coords,
2256 const SbVec3f * normals,
2257 SoMaterialBundle * mb,
2258 const SoTextureCoordinateBundle * COIN_UNUSED_ARG(tb),
2259 int32_t numpts,
2260 int32_t idx)
2261 {
2262 int matnr = 0;
2263
2264 glBegin(GL_POINTS);
2265 for (int i = 0; i < numpts; i++) {
2266 mb->send(matnr++, TRUE);
2267 glNormal3fv((const GLfloat*)normals++);
2268 coords->send(idx++);
2269 }
2270 glEnd();
2271 }
2272
2273 static void
sogl_render_pointset_m1n1t1(const SoGLCoordinateElement * coords,const SbVec3f * normals,SoMaterialBundle * mb,const SoTextureCoordinateBundle * tb,int32_t numpts,int32_t idx)2274 sogl_render_pointset_m1n1t1(const SoGLCoordinateElement * coords,
2275 const SbVec3f * normals,
2276 SoMaterialBundle * mb,
2277 const SoTextureCoordinateBundle * tb,
2278 int32_t numpts,
2279 int32_t idx)
2280 {
2281 int texnr = 0;
2282 int matnr = 0;
2283
2284 glBegin(GL_POINTS);
2285 for (int i = 0; i < numpts; i++) {
2286 mb->send(matnr++, TRUE);
2287 tb->send(texnr++, coords->get3(idx), *normals);
2288 glNormal3fv((const GLfloat*)normals++);
2289 coords->send(idx++);
2290 }
2291 glEnd();
2292 }
2293
2294 // ---
2295
2296 typedef void sogl_render_pointset_func(const SoGLCoordinateElement * coords,
2297 const SbVec3f * normals,
2298 SoMaterialBundle * mb,
2299 const SoTextureCoordinateBundle * tb,
2300 int32_t numpts,
2301 int32_t idx);
2302
2303 static sogl_render_pointset_func * sogl_render_pointset_funcs[8];
2304
2305 void
sogl_render_pointset(const SoGLCoordinateElement * coords,const SbVec3f * normals,SoMaterialBundle * mb,const SoTextureCoordinateBundle * tb,int32_t numpts,int32_t idx)2306 sogl_render_pointset(const SoGLCoordinateElement * coords,
2307 const SbVec3f * normals,
2308 SoMaterialBundle * mb,
2309 const SoTextureCoordinateBundle * tb,
2310 int32_t numpts,
2311 int32_t idx)
2312 {
2313 static int first = 1;
2314 if (first) {
2315 sogl_render_pointset_funcs[0] = sogl_render_pointset_m0n0t0;
2316 sogl_render_pointset_funcs[1] = sogl_render_pointset_m0n0t1;
2317 sogl_render_pointset_funcs[2] = sogl_render_pointset_m0n1t0;
2318 sogl_render_pointset_funcs[3] = sogl_render_pointset_m0n1t1;
2319 sogl_render_pointset_funcs[4] = sogl_render_pointset_m1n0t0;
2320 sogl_render_pointset_funcs[5] = sogl_render_pointset_m1n0t1;
2321 sogl_render_pointset_funcs[6] = sogl_render_pointset_m1n1t0;
2322 sogl_render_pointset_funcs[7] = sogl_render_pointset_m1n1t1;
2323 first = 0;
2324 }
2325
2326 int mat = mb ? 1 : 0;
2327 int norm = normals ? 1 : 0;
2328 int tex = tb ? 1 : 0;
2329
2330 sogl_render_pointset_funcs[ (mat << 2) | (norm << 1) | tex ]
2331 ( coords,
2332 normals,
2333 mb,
2334 tb,
2335 numpts,
2336 idx);
2337 }
2338
2339 // Used by library code to decide whether or not to add extra
2340 // debugging checks for glGetError().
2341 SbBool
sogl_glerror_debugging(void)2342 sogl_glerror_debugging(void)
2343 {
2344 static int COIN_GLERROR_DEBUGGING = -1;
2345 if (COIN_GLERROR_DEBUGGING == -1) {
2346 const char * str = coin_getenv("COIN_GLERROR_DEBUGGING");
2347 COIN_GLERROR_DEBUGGING = str ? atoi(str) : 0;
2348 }
2349 return (COIN_GLERROR_DEBUGGING == 0) ? FALSE : TRUE;
2350 }
2351
2352 static int SOGL_AUTOCACHE_REMOTE_MIN = 500000;
2353 static int SOGL_AUTOCACHE_REMOTE_MAX = 5000000;
2354 static int SOGL_AUTOCACHE_LOCAL_MIN = 100000;
2355 static int SOGL_AUTOCACHE_LOCAL_MAX = 1000000;
2356 static int SOGL_AUTOCACHE_VBO_LIMIT = 65536;
2357
2358 /*!
2359 Called by each shape during rendering. Will enable/disable autocaching
2360 based on the number of primitives.
2361 */
2362 void
sogl_autocache_update(SoState * state,const int numprimitives,SbBool didusevbo)2363 sogl_autocache_update(SoState * state, const int numprimitives, SbBool didusevbo)
2364 {
2365 static SbBool didtestenv = FALSE;
2366 if (!didtestenv) {
2367 const char * env;
2368 env = coin_getenv("COIN_AUTOCACHE_REMOTE_MIN");
2369 if (env) {
2370 SOGL_AUTOCACHE_REMOTE_MIN = atoi(env);
2371 }
2372 env = coin_getenv("COIN_AUTOCACHE_REMOTE_MAX");
2373 if (env) {
2374 SOGL_AUTOCACHE_REMOTE_MAX = atoi(env);
2375 }
2376 env = coin_getenv("COIN_AUTOCACHE_LOCAL_MIN");
2377 if (env) {
2378 SOGL_AUTOCACHE_LOCAL_MIN = atoi(env);
2379 }
2380 env = coin_getenv("COIN_AUTOCACHE_LOCAL_MAX");
2381 if (env) {
2382 SOGL_AUTOCACHE_LOCAL_MAX = atoi(env);
2383 }
2384 env = coin_getenv("COIN_AUTOCACHE_VBO_LIMIT");
2385 if (env) {
2386 SOGL_AUTOCACHE_VBO_LIMIT = atoi(env);
2387 }
2388 didtestenv = TRUE;
2389 }
2390
2391 int minval = SOGL_AUTOCACHE_LOCAL_MIN;
2392 int maxval = SOGL_AUTOCACHE_LOCAL_MAX;
2393 if (SoGLCacheContextElement::getIsRemoteRendering(state)) {
2394 minval = SOGL_AUTOCACHE_REMOTE_MIN;
2395 maxval = SOGL_AUTOCACHE_REMOTE_MAX;
2396 }
2397 if (numprimitives <= minval) {
2398 SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DO_AUTO_CACHE);
2399 }
2400 else if (numprimitives >= maxval) {
2401 SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE);
2402 }
2403 SoGLCacheContextElement::incNumShapes(state);
2404
2405 if (didusevbo) {
2406 // avoid creating caches when rendering large VBOs
2407 if (numprimitives > SOGL_AUTOCACHE_VBO_LIMIT) {
2408 SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE);
2409 }
2410 }
2411 }
2412
2413 // **************************************************************************
2414
2415 static SoOffscreenRenderer * offscreenrenderer = NULL;
2416 static SoCallback * offscreencallback = NULL;
2417
offscreenrenderer_cleanup(void)2418 static void offscreenrenderer_cleanup(void)
2419 {
2420 offscreencallback->unref();
2421 delete offscreenrenderer;
2422 offscreenrenderer = NULL;
2423 offscreencallback = NULL;
2424 }
2425
2426 // This is really obsoleted now that we have
2427 // cc_glglue_context_create_offscreen() et al in the OpenGL
2428 // wrapper. So don't use this function any more from within Coin.
2429 //
2430 // FIXME: must be kept around due to ABI & API compatibility reasons
2431 // for now, but should consider taking it out for the next major Coin
2432 // release.
2433 //
2434 // 20030519 mortene.
2435 //
2436 // SoGL API is private so this function can be taken out any time
2437 // 20090426 pederb
2438
2439 void
sogl_offscreencontext_callback(void (* cb)(void *,SoAction *),void * closure)2440 sogl_offscreencontext_callback(void (*cb)(void *, SoAction*),
2441 void * closure)
2442 {
2443 if (offscreenrenderer == NULL) {
2444 offscreenrenderer = new SoOffscreenRenderer(SbViewportRegion(32, 32));
2445 offscreencallback = new SoCallback;
2446 offscreencallback->ref();
2447 coin_atexit((coin_atexit_f*) offscreenrenderer_cleanup, CC_ATEXIT_NORMAL);
2448 }
2449 offscreencallback->setCallback(cb, closure);
2450 offscreenrenderer->render(offscreencallback);
2451 }
2452