SoFCIndexedFaceSet.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2009 Werner Mayer <wmayer[at]users.sourceforge.net>     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 # include <algorithm>
00028 # ifdef FC_OS_MACOSX
00029 # include <OpenGL/gl.h>
00030 # include <OpenGL/glu.h>
00031 # else
00032 # include <GL/gl.h>
00033 # include <GL/glu.h>
00034 # endif
00035 # include <Inventor/actions/SoGLRenderAction.h>
00036 # include <Inventor/bundles/SoMaterialBundle.h>
00037 # include <Inventor/elements/SoCoordinateElement.h>
00038 # include <Inventor/elements/SoGLCoordinateElement.h>
00039 # include <Inventor/elements/SoMaterialBindingElement.h>
00040 # include <Inventor/elements/SoProjectionMatrixElement.h>
00041 # include <Inventor/elements/SoViewingMatrixElement.h>
00042 #endif
00043 
00044 #include <Gui/SoFCInteractiveElement.h>
00045 #include <Gui/SoFCSelectionAction.h>
00046 #include "SoFCIndexedFaceSet.h"
00047 
00048 using namespace MeshGui;
00049 
00050 
00051 SO_NODE_SOURCE(SoFCIndexedFaceSet);
00052 
00053 void SoFCIndexedFaceSet::initClass()
00054 {
00055     SO_NODE_INIT_CLASS(SoFCIndexedFaceSet, SoIndexedFaceSet, "IndexedFaceSet");
00056 }
00057 
00058 SoFCIndexedFaceSet::SoFCIndexedFaceSet() : renderTriangleLimit(100000), selectBuf(0)
00059 {
00060     SO_NODE_CONSTRUCTOR(SoFCIndexedFaceSet);
00061     setName(SoFCIndexedFaceSet::getClassTypeId().getName());
00062 }
00063 
00067 void SoFCIndexedFaceSet::GLRender(SoGLRenderAction *action)
00068 {
00069     if (this->coordIndex.getNum() < 3)
00070         return;
00071 
00072     if (!this->shouldGLRender(action))
00073         return;
00074 
00075     SoState * state = action->getState();
00076     SbBool mode = Gui::SoFCInteractiveElement::get(state);
00077 
00078     unsigned int num = this->coordIndex.getNum()/4;
00079     if (mode == false || num <= this->renderTriangleLimit) {
00080         inherited::GLRender(action);
00081     }
00082     else {
00083         SoMaterialBindingElement::Binding matbind =
00084             SoMaterialBindingElement::get(state);
00085         int32_t binding = (int32_t)(matbind);
00086 
00087         const SoCoordinateElement * coords;
00088         const SbVec3f * normals;
00089         const int32_t * cindices;
00090         int numindices;
00091         const int32_t * nindices;
00092         const int32_t * tindices;
00093         const int32_t * mindices;
00094         SbBool normalCacheUsed;
00095 
00096         SoMaterialBundle mb(action);
00097 
00098         SoTextureCoordinateBundle tb(action, TRUE, FALSE);
00099         SbBool sendNormals = !mb.isColorOnly() || tb.isFunction();
00100 
00101         this->getVertexData(state, coords, normals, cindices,
00102                             nindices, tindices, mindices, numindices,
00103                             sendNormals, normalCacheUsed);
00104 
00105         mb.sendFirst(); // make sure we have the correct material
00106 
00107         drawCoords(static_cast<const SoGLCoordinateElement*>(coords), cindices, numindices,
00108                    normals, nindices, &mb, mindices, binding, &tb, tindices);
00109         // Disable caching for this node
00110         SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE);
00111     }
00112 }
00113 
00114 void SoFCIndexedFaceSet::drawCoords(const SoGLCoordinateElement * const vertexlist,
00115                                     const int32_t *vertexindices,
00116                                     int numindices,
00117                                     const SbVec3f *normals,
00118                                     const int32_t *normalindices,
00119                                     SoMaterialBundle *materials,
00120                                     const int32_t *matindices,
00121                                     const int32_t binding,
00122                                     const SoTextureCoordinateBundle * const texcoords,
00123                                     const int32_t *texindices)
00124 {
00125     const SbVec3f * coords3d = 0;
00126     coords3d = vertexlist->getArrayPtr3();
00127 
00128     int mod = numindices/(4*this->renderTriangleLimit)+1;
00129     float size = std::min<float>((float)mod,3.0f);
00130     glPointSize(size);
00131 
00132     SbBool per_face = FALSE;
00133     SbBool per_vert = FALSE;
00134     switch (binding) {
00135         case SoMaterialBindingElement::PER_FACE:
00136             per_face = TRUE;
00137             break;
00138         case SoMaterialBindingElement::PER_VERTEX:
00139             per_vert = TRUE;
00140             break;
00141         default:
00142             break;
00143     }
00144 
00145     int ct=0;
00146     const int32_t *viptr = vertexindices;
00147     int32_t v1, v2, v3;
00148     SbVec3f dummynormal(0,0,1);
00149     const SbVec3f *currnormal = &dummynormal;
00150     if (normals) currnormal = normals;
00151 
00152     glBegin(GL_POINTS);
00153     for (int index=0; index<numindices; ct++) {
00154         if (ct%mod==0) {
00155             if (per_face)
00156                 materials->send(ct, TRUE);
00157             v1 = *viptr++; index++;
00158             if (per_vert)
00159                 materials->send(v1, TRUE);
00160             if (normals)
00161                 currnormal = &normals[*normalindices++];
00162             glNormal3fv((const GLfloat*)currnormal);
00163             glVertex3fv((const GLfloat*)(coords3d + v1));
00164 
00165             v2 = *viptr++; index++;
00166             if (per_vert)
00167                 materials->send(v2, TRUE);
00168             if (normals)
00169                 currnormal = &normals[*normalindices++];
00170             glNormal3fv((const GLfloat*)currnormal);
00171             glVertex3fv((const GLfloat*)(coords3d + v2));
00172 
00173             v3 = *viptr++; index++;
00174             if (per_vert)
00175                 materials->send(v3, TRUE);
00176             if (normals)
00177                 currnormal = &normals[*normalindices++];
00178             glNormal3fv((const GLfloat*)currnormal);
00179             glVertex3fv((const GLfloat*)(coords3d + v3));
00180         }
00181         else {
00182             viptr++; index++; normalindices++;
00183             viptr++; index++; normalindices++;
00184             viptr++; index++; normalindices++;
00185         }
00186 
00187         viptr++; index++; normalindices++;
00188     }
00189     glEnd();
00190 }
00191 
00192 void SoFCIndexedFaceSet::doAction(SoAction * action)
00193 {
00194     if (action->getTypeId() == Gui::SoGLSelectAction::getClassTypeId()) {
00195         SoNode* node = action->getNodeAppliedTo();
00196         if (!node) return; // on no node applied
00197 
00198         // The node we have is the parent of this node and the coordinate node
00199         // thus we search there for it.
00200         SoSearchAction sa;
00201         sa.setInterest(SoSearchAction::FIRST);
00202         sa.setSearchingAll(FALSE);
00203         sa.setType(SoCoordinate3::getClassTypeId(), 1);
00204         sa.apply(node);
00205         SoPath * path = sa.getPath();
00206         if (!path) return;
00207 
00208         // make sure we got the node we wanted
00209         SoNode* coords = path->getNodeFromTail(0);
00210         if (!(coords && coords->getTypeId().isDerivedFrom(SoCoordinate3::getClassTypeId())))
00211             return;
00212         startSelection(action);
00213         renderSelectionGeometry(static_cast<SoCoordinate3*>(coords)->point.getValues(0));
00214         stopSelection(action);
00215     }
00216     else if (action->getTypeId() == Gui::SoVisibleFaceAction::getClassTypeId()) {
00217         SoNode* node = action->getNodeAppliedTo();
00218         if (!node) return; // on no node applied
00219 
00220         // The node we have is the parent of this node and the coordinate node
00221         // thus we search there for it.
00222         SoSearchAction sa;
00223         sa.setInterest(SoSearchAction::FIRST);
00224         sa.setSearchingAll(FALSE);
00225         sa.setType(SoCoordinate3::getClassTypeId(), 1);
00226         sa.apply(node);
00227         SoPath * path = sa.getPath();
00228         if (!path) return;
00229 
00230         // make sure we got the node we wanted
00231         SoNode* coords = path->getNodeFromTail(0);
00232         if (!(coords && coords->getTypeId().isDerivedFrom(SoCoordinate3::getClassTypeId())))
00233             return;
00234         startVisibility(action);
00235         renderVisibleFaces(static_cast<SoCoordinate3*>(coords)->point.getValues(0));
00236         stopVisibility(action);
00237     }
00238 
00239     inherited::doAction(action);
00240 }
00241 
00242 void SoFCIndexedFaceSet::startSelection(SoAction * action)
00243 {
00244     Gui::SoGLSelectAction *doaction = static_cast<Gui::SoGLSelectAction*>(action);
00245     const SbViewportRegion& vp = doaction->getViewportRegion();
00246     int x = vp.getViewportOriginPixels()[0];
00247     int y = vp.getViewportOriginPixels()[1];
00248     int w = vp.getViewportSizePixels()[0];
00249     int h = vp.getViewportSizePixels()[1];
00250 
00251     int bufSize = 5*(this->coordIndex.getNum()/4); // make the buffer big enough
00252     this->selectBuf = new GLuint[bufSize];
00253 
00254     SbMatrix view = SoViewingMatrixElement::get(action->getState());
00255     SbMatrix proj = SoProjectionMatrixElement::get(action->getState());
00256 
00257     glSelectBuffer(bufSize, selectBuf);
00258     glRenderMode(GL_SELECT);
00259 
00260     glInitNames();
00261     glPushName(-1);
00262 
00263     //double mp[16];
00264     GLint viewport[4];
00265     glGetIntegerv(GL_VIEWPORT,viewport);
00266     glMatrixMode(GL_PROJECTION);
00267     //glGetDoublev(GL_PROJECTION_MATRIX ,mp);
00268     glPushMatrix();
00269     glLoadIdentity();
00270     gluPickMatrix(x, y, w, h, viewport);
00271     glMultMatrixf(/*mp*/(float*)proj);
00272     glMatrixMode(GL_MODELVIEW);
00273     glPushMatrix();
00274     glLoadMatrixf((float*)view);
00275 }
00276 
00277 void SoFCIndexedFaceSet::stopSelection(SoAction * action)
00278 {
00279     // restoring the original projection matrix
00280     glPopMatrix();
00281     glMatrixMode(GL_PROJECTION);
00282     glPopMatrix();
00283     glMatrixMode(GL_MODELVIEW);
00284     glFlush();
00285 
00286     // returning to normal rendering mode
00287     GLint hits = glRenderMode(GL_RENDER);
00288 
00289     int bufSize = 5*(this->coordIndex.getNum()/4);
00290     std::vector< std::pair<double,unsigned int> > hit;
00291     GLint index=0;
00292     for (GLint ii=0;ii<hits && index<bufSize;ii++) {
00293         GLint ct = (GLint)selectBuf[index];
00294         hit.push_back(std::pair<double,unsigned int>
00295             (selectBuf[index+1]/4294967295.0,selectBuf[index+3]));
00296         index = index+ct+3;
00297     }
00298 
00299     delete [] selectBuf;
00300     selectBuf = 0;
00301     bool sorted = true;
00302     if(sorted) std::sort(hit.begin(),hit.end());
00303 
00304     Gui::SoGLSelectAction *doaction = static_cast<Gui::SoGLSelectAction*>(action);
00305     doaction->indices.reserve(hit.size());
00306     for (GLint ii=0;ii<hits;ii++) {
00307         doaction->indices.push_back(hit[ii].second);
00308     }
00309 }
00310 
00311 void SoFCIndexedFaceSet::renderSelectionGeometry(const SbVec3f * coords3d)
00312 {
00313     int numfaces = this->coordIndex.getNum()/4;
00314     const int32_t * cindices = this->coordIndex.getValues(0);
00315 
00316     int fcnt=0;
00317     int32_t v1, v2, v3;
00318     for (int index=0; index<numfaces;index++,cindices++) {
00319         glLoadName(fcnt);
00320         glBegin(GL_TRIANGLES);
00321             v1 = *cindices++;
00322             glVertex3fv((const GLfloat*)(coords3d + v1));
00323             v2 = *cindices++;
00324             glVertex3fv((const GLfloat*)(coords3d + v2));
00325             v3 = *cindices++;
00326             glVertex3fv((const GLfloat*)(coords3d + v3));
00327         glEnd();
00328         fcnt++;
00329     }
00330 }
00331 
00332 void SoFCIndexedFaceSet::startVisibility(SoAction * action)
00333 {
00334     SbMatrix view = SoViewingMatrixElement::get(action->getState());
00335     SbMatrix proj = SoProjectionMatrixElement::get(action->getState());
00336 
00337     glMatrixMode(GL_PROJECTION);
00338     glPushMatrix();
00339     glLoadIdentity();
00340     glMultMatrixf((float*)proj);
00341     glMatrixMode(GL_MODELVIEW);
00342     glPushMatrix();
00343     glLoadMatrixf((float*)view);
00344 }
00345 
00346 void SoFCIndexedFaceSet::stopVisibility(SoAction * action)
00347 {
00348     // restoring the original projection matrix
00349     glPopMatrix();
00350     glMatrixMode(GL_PROJECTION);
00351     glPopMatrix();
00352     glMatrixMode(GL_MODELVIEW);
00353     glFlush();
00354 }
00355 
00356 void SoFCIndexedFaceSet::renderVisibleFaces(const SbVec3f * coords3d)
00357 {
00358     //GLint redBits, greenBits, blueBits;
00359 
00360     //glGetIntegerv (GL_RED_BITS, &redBits);
00361     //glGetIntegerv (GL_GREEN_BITS, &greenBits);
00362     //glGetIntegerv (GL_BLUE_BITS, &blueBits);
00363     glDisable (GL_BLEND);
00364     glDisable (GL_DITHER);
00365     glDisable (GL_FOG);
00366     glDisable (GL_LIGHTING);
00367     glDisable (GL_TEXTURE_1D);
00368     glDisable (GL_TEXTURE_2D);
00369     glShadeModel (GL_FLAT);
00370 
00371     uint32_t numfaces = this->coordIndex.getNum()/4;
00372     const int32_t * cindices = this->coordIndex.getValues(0);
00373 
00374     int32_t v1, v2, v3;
00375     for (uint32_t index=0; index<numfaces;index++,cindices++) {
00376         glBegin(GL_TRIANGLES);
00377             float t;
00378             SbColor c;
00379             c.setPackedValue(index<<8,t);
00380             glColor3f(c[0],c[1],c[2]);
00381             v1 = *cindices++;
00382             glVertex3fv((const GLfloat*)(coords3d + v1));
00383             v2 = *cindices++;
00384             glVertex3fv((const GLfloat*)(coords3d + v2));
00385             v3 = *cindices++;
00386             glVertex3fv((const GLfloat*)(coords3d + v3));
00387         glEnd();
00388     }
00389 }

Generated on Wed Nov 23 19:00:39 2011 for FreeCAD by  doxygen 1.6.1