/**************************************************************************\ * * This file is part of the Coin 3D visualization library. * Copyright (C) 1998-2007 by Systems in Motion. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * ("GPL") version 2 as published by the Free Software Foundation. * See the file LICENSE.GPL at the root directory of this source * distribution for additional information about the GNU GPL. * * For using Coin with software that can not be combined with the GNU * GPL, and for taking advantage of the additional benefits of our * support services, please contact Systems in Motion about acquiring * a Coin Professional Edition License. * * See http://www.coin3d.org/ for more information. * * Systems in Motion, Postboks 1283, Pirsenteret, 7462 Trondheim, NORWAY. * http://www.sim.no/ sales@sim.no coin-support@coin3d.org * \**************************************************************************/ (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) { int texidx = 0; const SbVec3f * coords3d = NULL; const SbVec4f * coords4d = NULL; const SbBool is3d = vertexlist->is3D(); if (is3d) { coords3d = vertexlist->getArrayPtr3(); } else { coords4d = vertexlist->getArrayPtr4(); } // This is the same code as in SoGLCoordinateElement::send(). // It is inlined here for speed (~15% speed increase). #define SEND_VERTEX(_idx_) \ if (is3d) glVertex3fv((const GLfloat*) (coords3d + _idx_)); \ else glVertex4fv((const GLfloat*) (coords4d + _idx_)); int mode = GL_POLYGON; // ...to save a test int newmode; const int32_t *viptr = vertexindices; const int32_t *vistartptr = vertexindices; const int32_t *viendptr = viptr + numindices; int32_t v1, v2, v3, v4, v5 = 0; // v5 init unnecessary, but kills a compiler warning. SbVec3f dummynormal(0,0,1); int numverts = vertexlist->getNum(); #if NBINDING==PER_VERTEX || NBINDING==PER_FACE || NBINDING==PER_VERTEX_INDEXED || NBINDING==PER_FACE_INDEXED || TEXTURES==TRUE const SbVec3f *currnormal = &dummynormal; if (normals) currnormal = normals; #endif // currnormal wrapper int matnr = 0; while (viptr + 2 < viendptr) { v1 = *viptr++; v2 = *viptr++; v3 = *viptr++; // Variable used for counting errors and make sure not a // bunch of errormessages flood the screen. static uint32_t current_errors = 0; // This test is for robustness upon buggy data sets if (v1 < 0 || v2 < 0 || v3 < 0 || v1 >= numverts || v2 >= numverts || v3 >= numverts) { if (current_errors < 1) { SoDebugError::postWarning("[faceset]::GLRender", "Erroneous polygon detected. " "Ignoring (offset: %d, [%d %d %d]). Should be within " " [0, %d] This message will only be shown once, but " "more errors might be present", viptr - vistartptr - 3, v1, v2, v3, numverts - 1); } current_errors++; break; } v4 = viptr < viendptr ? *viptr++ : -1; if (v4 < 0) newmode = GL_TRIANGLES; // This test for numverts is for robustness upon buggy data sets else if (v4 >= numverts) { newmode = GL_TRIANGLES; if (current_errors < 1) { SoDebugError::postWarning("[faceset]::GLRender", "Erroneous polygon detected. " "(offset: %d, [%d %d %d %d]). Should be within " " [0, %d] This message will only be shown once, but " "more errors might be present", viptr - vistartptr - 4, v1, v2, v3, v4, numverts - 1); } current_errors++; } else { v5 = viptr < viendptr ? *viptr++ : -1; if (v5 < 0) newmode = GL_QUADS; // This test for numverts is for robustness upon buggy data sets else if (v5 >= numverts) { newmode = GL_QUADS; if (current_errors < 1) { SoDebugError::postWarning("[faceset]::GLRender", "Erroneous polygon detected. " "(offset: %d, [%d %d %d %d %d]). Should be within " " [0, %d] This message will only be shown once, but " "more errors might be present", viptr - vistartptr - 5, v1, v2, v3, v4, v5, numverts - 1); } current_errors++; } else newmode = GL_POLYGON; } if (newmode != mode) { if (mode != GL_POLYGON) glEnd(); mode = newmode; glBegin((GLenum) mode); } else if (mode == GL_POLYGON) glBegin(GL_POLYGON); /* vertex 1 *********************************************************/ #if MBINDING==PER_VERTEX || MBINDING==PER_FACE materials->send(matnr++, TRUE); #elif MBINDING==PER_VERTEX_INDEXED || MBINDING==PER_FACE_INDEXED materials->send(*matindices++, TRUE); #endif #if NBINDING==PER_VERTEX || NBINDING==PER_FACE currnormal = normals++; glNormal3fv((const GLfloat*)currnormal); #elif NBINDING==PER_VERTEX_INDEXED || NBINDING==PER_FACE_INDEXED currnormal = &normals[*normalindices++]; glNormal3fv((const GLfloat*)currnormal); #endif #if TEXTURES==TRUE texcoords->send(texindices ? *texindices++ : texidx++, vertexlist->get3(v1), *currnormal); #endif SEND_VERTEX(v1); /* vertex 2 *********************************************************/ #if MBINDING==PER_VERTEX materials->send(matnr++, TRUE); #elif MBINDING==PER_VERTEX_INDEXED materials->send(*matindices++, TRUE); #endif // nvidia color-per-face-bug workaround #if MBINDING==PER_FACE materials->send(matnr-1, TRUE); #elif MBINDING==PER_FACE_INDEXED materials->send(matindices[-1], TRUE); #endif #if NBINDING==PER_VERTEX currnormal = normals++; glNormal3fv((const GLfloat*)currnormal); #elif NBINDING==PER_VERTEX_INDEXED currnormal = &normals[*normalindices++]; glNormal3fv((const GLfloat*)currnormal); #endif #if TEXTURES==TRUE texcoords->send(texindices ? *texindices++ : texidx++, vertexlist->get3(v2), *currnormal); #endif SEND_VERTEX(v2); /* vertex 3 *********************************************************/ #if MBINDING==PER_VERTEX materials->send(matnr++, TRUE); #elif MBINDING==PER_VERTEX_INDEXED materials->send(*matindices++, TRUE); #endif // nvidia color-per-face-bug workaround #if MBINDING==PER_FACE materials->send(matnr-1, TRUE); #elif MBINDING==PER_FACE_INDEXED materials->send(matindices[-1], TRUE); #endif #if NBINDING==PER_VERTEX currnormal = normals++; glNormal3fv((const GLfloat*)currnormal); #elif NBINDING==PER_VERTEX_INDEXED currnormal = &normals[*normalindices++]; glNormal3fv((const GLfloat*)currnormal); #endif #if TEXTURES==TRUE texcoords->send(texindices ? *texindices++ : texidx++, vertexlist->get3(v3), *currnormal); #endif SEND_VERTEX(v3); if (mode != GL_TRIANGLES) { /* vertex 4 (quad or polygon)**************************************/ #if MBINDING==PER_VERTEX materials->send(matnr++, TRUE); #elif MBINDING==PER_VERTEX_INDEXED materials->send(*matindices++, TRUE); #endif // nvidia color-per-face-bug workaround #if MBINDING==PER_FACE materials->send(matnr-1, TRUE); #elif MBINDING==PER_FACE_INDEXED materials->send(matindices[-1], TRUE); #endif #if NBINDING==PER_VERTEX currnormal = normals++; glNormal3fv((const GLfloat*)currnormal); #elif NBINDING==PER_VERTEX_INDEXED currnormal = &normals[*normalindices++]; glNormal3fv((const GLfloat*)currnormal); #endif #if TEXTURES==TRUE texcoords->send(texindices ? *texindices++ : texidx++, vertexlist->get3(v4), *currnormal); #endif SEND_VERTEX(v4); if (mode == GL_POLYGON) { /* vertex 5 (polygon) ********************************************/ #if MBINDING==PER_VERTEX materials->send(matnr++, TRUE); #elif MBINDING==PER_VERTEX_INDEXED materials->send(*matindices++, TRUE); #endif // nvidia color-per-face-bug workaround #if MBINDING==PER_FACE materials->send(matnr-1, TRUE); #elif MBINDING==PER_FACE_INDEXED materials->send(matindices[-1], TRUE); #endif #if NBINDING==PER_VERTEX currnormal = normals++; glNormal3fv((const GLfloat*)currnormal); #elif NBINDING==PER_VERTEX_INDEXED currnormal = &normals[*normalindices++]; glNormal3fv((const GLfloat*)currnormal); #endif #if TEXTURES==TRUE texcoords->send(texindices ? *texindices++ : texidx++, vertexlist->get3(v5), *currnormal); #endif SEND_VERTEX(v5); v1 = viptr < viendptr ? *viptr++ : -1; while (v1 >= 0) { // For robustness upon buggy data sets if (v1 >= numverts) { if (current_errors < 1) { SoDebugError::postWarning("[faceset]::GLRender", "Erroneous polygon detected. " "(offset: %d, [... %d]). Should be within " "[0, %d] This message will only be shown once, but " "more errors might be present", viptr - vistartptr - 1, v1, numverts - 1); } current_errors++; break; } /* vertex 6-n (polygon) *****************************************/ #if MBINDING==PER_VERTEX materials->send(matnr++, TRUE); #elif MBINDING==PER_VERTEX_INDEXED materials->send(*matindices++, TRUE); #endif // nvidia color-per-face-bug workaround #if MBINDING==PER_FACE materials->send(matnr-1, TRUE); #elif MBINDING==PER_FACE_INDEXED materials->send(matindices[-1], TRUE); #endif #if NBINDING==PER_VERTEX currnormal = normals++; glNormal3fv((const GLfloat*)currnormal); #elif NBINDING==PER_VERTEX_INDEXED currnormal = &normals[*normalindices++]; glNormal3fv((const GLfloat*)currnormal); #endif #if TEXTURES==TRUE texcoords->send(texindices ? *texindices++ : texidx++, vertexlist->get3(v1), *currnormal); #endif SEND_VERTEX(v1); v1 = viptr < viendptr ? *viptr++ : -1; } glEnd(); /* draw polygon */ } } #if MBINDING==PER_VERTEX_INDEXED matindices++; #endif #if NBINDING==PER_VERTEX_INDEXED normalindices++; #endif #if TEXTURES==TRUE if (texindices) texindices++; #endif } // check if triangle or quad if (mode != GL_POLYGON) glEnd(); } #undef SEND_VERTEX