SoFCMeshNode.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2006 Werner Mayer <werner.wm.mayer@gmx.de>              *
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 # ifdef FC_OS_WIN32
00028 # include <windows.h>
00029 # endif
00030 # ifdef FC_OS_MACOSX
00031 # include <OpenGL/gl.h>
00032 # else
00033 # include <GL/gl.h>
00034 # endif
00035 # include <Inventor/SbBox.h>
00036 # include <Inventor/SoOutput.h>
00037 # include <Inventor/SoPrimitiveVertex.h>
00038 # include <Inventor/actions/SoGLRenderAction.h>
00039 # include <Inventor/actions/SoGetPrimitiveCountAction.h>
00040 # include <Inventor/actions/SoWriteAction.h>
00041 # include <Inventor/bundles/SoMaterialBundle.h>
00042 # include <Inventor/bundles/SoTextureCoordinateBundle.h>
00043 # include <Inventor/details/SoFaceDetail.h>
00044 # include <Inventor/details/SoPointDetail.h>
00045 # include <Inventor/elements/SoGLCacheContextElement.h>
00046 # include <Inventor/elements/SoLazyElement.h>
00047 # include <Inventor/elements/SoLightModelElement.h>
00048 # include <Inventor/misc/SoState.h>
00049 #endif
00050 
00051 #include <Gui/SoFCInteractiveElement.h>
00052 #include <Mod/Mesh/App/Core/Elements.h>
00053 #include <Mod/Mesh/App/Core/Grid.h>
00054 #include <Mod/Mesh/App/Core/Algorithm.h>
00055 #include <Mod/Mesh/App/Core/MeshIO.h>
00056 #include <Mod/Mesh/App/Mesh.h>
00057 #include "SoFCMeshNode.h"
00058 
00059 using namespace MeshGui;
00060 
00078 // Helper functions: draw vertices
00079 inline void glVertex(const MeshCore::MeshPoint& _v)  
00080 { 
00081   float v[3];
00082   v[0]=_v.x; v[1]=_v.y;v[2]=_v.z;
00083   glVertex3fv(v); 
00084 }
00085 
00086 // Helper functions: draw normal
00087 inline void glNormal(const Base::Vector3f& _n)
00088 { 
00089   float n[3];
00090   n[0]=_n.x; n[1]=_n.y;n[2]=_n.z;
00091   glNormal3fv(n); 
00092 }
00093 
00094 // Helper functions: draw normal
00095 inline void glNormal(float* n)
00096 { 
00097   glNormal3fv(n); 
00098 }
00099 
00100 // Helper function: convert Vec to SbVec3f
00101 inline SbVec3f sbvec3f(const Base::Vector3f& _v) {
00102   return SbVec3f(_v.x, _v.y, _v.z); 
00103 }
00104 
00105 SO_NODE_SOURCE(SoFCMeshNode);
00106 
00107 void SoFCMeshNode::initClass()
00108 {
00109   SO_NODE_INIT_CLASS(SoFCMeshNode, SoShape, "Shape");
00110 }
00111 
00112 SoFCMeshNode::SoFCMeshNode() : MaximumTriangles(500000), _mesh(0), _ctPrimitives(0)
00113 {
00114   SO_NODE_CONSTRUCTOR(SoFCMeshNode);
00115   SO_NODE_ADD_FIELD(point, (0.0f, 0.0f, 0.0f));
00116   SO_NODE_ADD_FIELD(coordIndex,(0));
00117 }
00118 
00119 void SoFCMeshNode::notify(SoNotList * node)
00120 {
00121   SoShape::notify(node);
00122 }
00123 
00127 void SoFCMeshNode::setMesh(const Mesh::MeshObject* mesh)
00128 { 
00129   _mesh = mesh; 
00130 }
00131 
00144 void SoFCMeshNode::createRoughModel(bool simplest)
00145 {
00146   const Base::BoundBox3f& cBox = _mesh->getKernel().GetBoundBox();
00147 
00148   if ( simplest ) {
00149     int triangles[36] = {
00150       0,1,2,0,2,3,
00151       0,1,5,0,5,4,
00152       0,4,7,0,7,3,
00153       6,7,4,6,4,5,
00154       6,2,3,6,3,7,
00155       6,1,2,6,5,1
00156     };
00157     SbVec3f points[8] = {
00158       SbVec3f(cBox.MinX,cBox.MinY,cBox.MinZ),
00159       SbVec3f(cBox.MaxX,cBox.MinY,cBox.MinZ),
00160       SbVec3f(cBox.MaxX,cBox.MaxY,cBox.MinZ),
00161       SbVec3f(cBox.MinX,cBox.MaxY,cBox.MinZ),
00162       SbVec3f(cBox.MinX,cBox.MinY,cBox.MaxZ),
00163       SbVec3f(cBox.MaxX,cBox.MinY,cBox.MaxZ),
00164       SbVec3f(cBox.MaxX,cBox.MaxY,cBox.MaxZ),
00165       SbVec3f(cBox.MinX,cBox.MaxY,cBox.MaxZ)
00166     };
00167 
00168     coordIndex.setValues(0,36,triangles);
00169     point.setValues (0,8,points);
00170   } else {
00171     // Check the boundings and the average edge length
00172     float fAvgLen = 5.0f * MeshCore::MeshAlgorithm(_mesh->getKernel()).GetAverageEdgeLength();
00173 
00174     // create maximum 50 grids in each direction 
00175     fAvgLen = std::max<float>(fAvgLen, (cBox.MaxX-cBox.MinX)/50.0f);
00176     fAvgLen = std::max<float>(fAvgLen, (cBox.MaxY-cBox.MinY)/50.0f);
00177     fAvgLen = std::max<float>(fAvgLen, (cBox.MaxZ-cBox.MinZ)/50.0f);
00178 
00179     MeshCore::MeshGeomFacet face;
00180     std::vector<MeshCore::MeshGeomFacet> facets;
00181 
00182     MeshCore::MeshPointGrid cGrid(_mesh->getKernel(), fAvgLen);
00183     unsigned long ulMaxX, ulMaxY, ulMaxZ;
00184     cGrid.GetCtGrids(ulMaxX, ulMaxY, ulMaxZ);
00185     MeshCore::MeshGridIterator cIter(cGrid);
00186 
00187     for ( cIter.Init(); cIter.More(); cIter.Next() ) {
00188       if ( cIter.GetCtElements() > 0 ) {
00189         unsigned long ulX, ulY, ulZ;
00190         cIter.GetGridPos(ulX, ulY, ulZ);
00191         Base::BoundBox3f cBox = cIter.GetBoundBox();
00192 
00193         if ( ulX == 0 || (ulX-1 >= 0 && cGrid.GetCtElements(ulX-1,ulY, ulZ) == 0) ) {
00194           face._aclPoints[0].Set(cBox.MinX,cBox.MinY,cBox.MinZ);
00195           face._aclPoints[1].Set(cBox.MinX,cBox.MinY,cBox.MaxZ);
00196           face._aclPoints[2].Set(cBox.MinX,cBox.MaxY,cBox.MinZ);
00197           facets.push_back(face);
00198           face._aclPoints[0].Set(cBox.MinX,cBox.MaxY,cBox.MaxZ);
00199           face._aclPoints[1].Set(cBox.MinX,cBox.MaxY,cBox.MinZ);
00200           face._aclPoints[2].Set(cBox.MinX,cBox.MinY,cBox.MaxZ);
00201           facets.push_back(face);
00202         }
00203         if ( ulX+1 == ulMaxX || (ulX+1 < ulMaxX && cGrid.GetCtElements(ulX+1,ulY, ulZ) == 0) ) {
00204           face._aclPoints[0].Set(cBox.MaxX,cBox.MinY,cBox.MinZ);
00205           face._aclPoints[1].Set(cBox.MaxX,cBox.MaxY,cBox.MinZ);
00206           face._aclPoints[2].Set(cBox.MaxX,cBox.MinY,cBox.MaxZ);
00207           facets.push_back(face);
00208           face._aclPoints[0].Set(cBox.MaxX,cBox.MaxY,cBox.MaxZ);
00209           face._aclPoints[1].Set(cBox.MaxX,cBox.MinY,cBox.MaxZ);
00210           face._aclPoints[2].Set(cBox.MaxX,cBox.MaxY,cBox.MinZ);
00211           facets.push_back(face);
00212         }
00213         if ( ulY == 0 || (ulY-1 >= 0 && cGrid.GetCtElements(ulX,ulY-1, ulZ) == 0) ) {
00214           face._aclPoints[0].Set(cBox.MinX,cBox.MinY,cBox.MaxZ);
00215           face._aclPoints[1].Set(cBox.MinX,cBox.MinY,cBox.MinZ);
00216           face._aclPoints[2].Set(cBox.MaxX,cBox.MinY,cBox.MaxZ);
00217           facets.push_back(face);
00218           face._aclPoints[0].Set(cBox.MaxX,cBox.MinY,cBox.MinZ);
00219           face._aclPoints[1].Set(cBox.MaxX,cBox.MinY,cBox.MaxZ);
00220           face._aclPoints[2].Set(cBox.MinX,cBox.MinY,cBox.MinZ);
00221           facets.push_back(face);
00222         }
00223         if ( ulY+1 == ulMaxY || (ulY+1 < ulMaxY && cGrid.GetCtElements(ulX,ulY+1, ulZ) == 0) ) {
00224           face._aclPoints[0].Set(cBox.MaxX,cBox.MaxY,cBox.MinZ);
00225           face._aclPoints[1].Set(cBox.MinX,cBox.MaxY,cBox.MinZ);
00226           face._aclPoints[2].Set(cBox.MaxX,cBox.MaxY,cBox.MaxZ);
00227           facets.push_back(face);
00228           face._aclPoints[0].Set(cBox.MinX,cBox.MaxY,cBox.MaxZ);
00229           face._aclPoints[1].Set(cBox.MaxX,cBox.MaxY,cBox.MaxZ);
00230           face._aclPoints[2].Set(cBox.MinX,cBox.MaxY,cBox.MinZ);
00231           facets.push_back(face);
00232         }
00233         if ( ulZ == 0 || (ulZ-1 >= 0 && cGrid.GetCtElements(ulX,ulY, ulZ-1) == 0) ) {
00234           face._aclPoints[0].Set(cBox.MaxX,cBox.MinY,cBox.MinZ);
00235           face._aclPoints[1].Set(cBox.MinX,cBox.MinY,cBox.MinZ);
00236           face._aclPoints[2].Set(cBox.MaxX,cBox.MaxY,cBox.MinZ);
00237           facets.push_back(face);
00238           face._aclPoints[0].Set(cBox.MinX,cBox.MaxY,cBox.MinZ);
00239           face._aclPoints[1].Set(cBox.MaxX,cBox.MaxY,cBox.MinZ);
00240           face._aclPoints[2].Set(cBox.MinX,cBox.MinY,cBox.MinZ);
00241           facets.push_back(face);
00242         }
00243         if ( ulZ+1 == ulMaxZ || (ulZ+1 < ulMaxZ && cGrid.GetCtElements(ulX,ulY, ulZ+1) == 0) ) {
00244           face._aclPoints[0].Set(cBox.MaxX,cBox.MinY,cBox.MaxZ);
00245           face._aclPoints[1].Set(cBox.MaxX,cBox.MaxY,cBox.MaxZ);
00246           face._aclPoints[2].Set(cBox.MinX,cBox.MinY,cBox.MaxZ);
00247           facets.push_back(face);
00248           face._aclPoints[0].Set(cBox.MinX,cBox.MaxY,cBox.MaxZ);
00249           face._aclPoints[1].Set(cBox.MinX,cBox.MinY,cBox.MaxZ);
00250           face._aclPoints[2].Set(cBox.MaxX,cBox.MaxY,cBox.MaxZ);
00251           facets.push_back(face);
00252         }
00253       }
00254     }
00255 
00256     MeshCore::MeshKernel kernel; kernel = facets;
00257     const MeshCore::MeshPointArray& rPoints = kernel.GetPoints();
00258     const MeshCore::MeshFacetArray& rFacets = kernel.GetFacets();
00259 
00260     point.enableNotify(false);
00261     point.setNum(rPoints.size());
00262     unsigned int pos=0;
00263     for (MeshCore::MeshPointArray::_TConstIterator cP=rPoints.begin(); cP!=rPoints.end(); ++cP)
00264       point.set1Value(pos++,cP->x,cP->y,cP->z);
00265     point.enableNotify(true);
00266 
00267     coordIndex.enableNotify(false);
00268     coordIndex.setNum(3*rFacets.size());
00269     pos=0;
00270     for (MeshCore::MeshFacetArray::_TConstIterator cF=rFacets.begin(); cF!=rFacets.end(); ++cF){
00271       coordIndex.set1Value(pos++,cF->_aulPoints[0]);
00272       coordIndex.set1Value(pos++,cF->_aulPoints[1]);
00273       coordIndex.set1Value(pos++,cF->_aulPoints[2]);
00274     }
00275     coordIndex.enableNotify(true);
00276 
00277     point.touch();
00278     coordIndex.touch();
00279 
00280 #ifdef FC_DEBUG
00281     std::ofstream str( "bbox.stl", std::ios::out | std::ios::binary );
00282     MeshCore::MeshOutput aWriter(kernel);
00283     aWriter.SaveBinarySTL( str );
00284 #endif
00285   }
00286 }
00287 
00291 void SoFCMeshNode::GLRender(SoGLRenderAction *action)
00292 {
00293   if (_mesh && shouldGLRender(action))
00294   {
00295     SoState*  state = action->getState();
00296 
00297     SbBool mode = Gui::SoFCInteractiveElement::get(state);
00298 
00299     //Binding mbind = this->findMaterialBinding(state);
00300 
00301     SoMaterialBundle mb(action);
00302     //SoTextureCoordinateBundle tb(action, true, false);
00303 
00304     SbBool needNormals = !mb.isColorOnly()/* || tb.isFunction()*/;
00305     mb.sendFirst();  // make sure we have the correct material
00306 
00307     //SbBool ccw = TRUE;
00308     //if (SoShapeHintsElement::getVertexOrdering(state) == SoShapeHintsElement::CLOCKWISE) 
00309     //  ccw = FALSE;
00310 
00311     if ( mode == false || countTriangles() <= this->MaximumTriangles )
00312       drawFaces(needNormals);
00313     else
00314       drawPoints(needNormals);
00315 
00316     // Disable caching for this node
00317     SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE);
00318   }
00319 }
00320 
00324 void SoFCMeshNode::drawFaces(SbBool needNormals) const
00325 {
00326   // Use the data structure directly and not through MeshFacetIterator as this
00327   // class is quite slowly (at least for rendering)
00328   const MeshCore::MeshPointArray& rPoints = _mesh->getKernel().GetPoints();
00329   const MeshCore::MeshFacetArray& rFacets = _mesh->getKernel().GetFacets();
00330 
00331   if (needNormals)
00332   {
00333     glBegin(GL_TRIANGLES);
00334     for ( MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it )
00335     {
00336       const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[0]];
00337       const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[1]];
00338       const MeshCore::MeshPoint& v2 = rPoints[it->_aulPoints[2]];
00339 
00340       // Calculate the normal n = (v1-v0)x(v2-v0)
00341       float n[3];
00342       n[0] = (v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y);
00343       n[1] = (v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z);
00344       n[2] = (v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x);
00345       
00346       glNormal(n);
00347       glVertex(v0);
00348       glVertex(v1);
00349       glVertex(v2);
00350     }
00351     glEnd();
00352   }
00353   else 
00354   {
00355     glBegin(GL_TRIANGLES);
00356     for ( MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it )
00357     {
00358       glVertex(rPoints[it->_aulPoints[0]]);
00359       glVertex(rPoints[it->_aulPoints[1]]);
00360       glVertex(rPoints[it->_aulPoints[2]]);
00361     }
00362     glEnd();
00363   }
00364 }
00365 
00369 void SoFCMeshNode::drawPoints(SbBool needNormals) const
00370 {
00371   // Use the data structure directly and not through MeshFacetIterator as this
00372   // class is quite slowly (at least for rendering)
00373   const MeshCore::MeshPointArray& rPoints = _mesh->getKernel().GetPoints();
00374   const MeshCore::MeshFacetArray& rFacets = _mesh->getKernel().GetFacets();
00375   int mod = rFacets.size()/MaximumTriangles+1;
00376 
00377   float size = std::min<float>((float)mod,3.0f);
00378   glPointSize(size);
00379 
00380   if (needNormals)
00381   {
00382     glBegin(GL_POINTS);
00383     int ct=0;
00384     for ( MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it, ct++ )
00385     {
00386       if ( ct%mod==0 ) {
00387         const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[0]];
00388         const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[1]];
00389         const MeshCore::MeshPoint& v2 = rPoints[it->_aulPoints[2]];
00390 
00391         // Calculate the normal n = (v1-v0)x(v2-v0)
00392         float n[3];
00393         n[0] = (v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y);
00394         n[1] = (v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z);
00395         n[2] = (v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x);
00396       
00397         // Calculate the center point p=(v0+v1+v2)/3
00398         float p[3];
00399         p[0] = (v0.x+v1.x+v2.x)/3.0f;
00400         p[1] = (v0.y+v1.y+v2.y)/3.0f;
00401         p[2] = (v0.z+v1.z+v2.z)/3.0f;
00402         glNormal3fv(n);
00403         glVertex3fv(p);
00404       }
00405     }
00406     glEnd();
00407   }
00408   else 
00409   {
00410     glBegin(GL_POINTS);
00411     int ct=0;
00412     for ( MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it, ct++ )
00413     {
00414       if (ct%mod==0) {
00415         const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[0]];
00416         const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[1]];
00417         const MeshCore::MeshPoint& v2 = rPoints[it->_aulPoints[2]];
00418         // Calculate the center point p=(v0+v1+v2)/3
00419         float p[3];
00420         p[0] = (v0.x+v1.x+v2.x)/3.0f;
00421         p[1] = (v0.y+v1.y+v2.y)/3.0f;
00422         p[2] = (v0.z+v1.z+v2.z)/3.0f;
00423         glVertex3fv(p);
00424       }
00425     }
00426     glEnd();
00427   }
00428 }
00429 
00435 void SoFCMeshNode::generatePrimitives(SoAction* action)
00436 {
00437   if (_mesh)
00438   {
00439     // Use the data structure directly and not through MeshFacetIterator as this
00440     // class is quite slowly (at least for rendering)
00441     const MeshCore::MeshPointArray& rPoints = _mesh->getKernel().GetPoints();
00442     const MeshCore::MeshFacetArray& rFacets = _mesh->getKernel().GetFacets();
00443 
00444     // In case we have too many triangles we just create a rough model of the original mesh
00445     if ( this->MaximumTriangles < rFacets.size() ) {
00446       //FIXME: We should notify this shape when the data has changed.
00447       //Just counting the number of triangles won't always work.
00448       if ( rFacets.size() != _ctPrimitives ) {
00449         _ctPrimitives = rFacets.size();
00450         createRoughModel(false);
00451       }
00452       SoPrimitiveVertex vertex;
00453       beginShape(action, TRIANGLES, 0);
00454       int i=0;
00455       while ( i<coordIndex.getNum() )
00456       {
00457         const SbVec3f& v0 = point[coordIndex[i++]]; 
00458         const SbVec3f& v1 = point[coordIndex[i++]]; 
00459         const SbVec3f& v2 = point[coordIndex[i++]]; 
00460 
00461         // Calculate the normal n = (v1-v0)x(v2-v0)
00462         SbVec3f n;
00463         n[0] = (v1[1]-v0[1])*(v2[2]-v0[2])-(v1[2]-v0[2])*(v2[1]-v0[1]);
00464         n[1] = (v1[2]-v0[2])*(v2[0]-v0[0])-(v1[0]-v0[0])*(v2[2]-v0[2]);
00465         n[2] = (v1[0]-v0[0])*(v2[1]-v0[1])-(v1[1]-v0[1])*(v2[0]-v0[0]);
00466 
00467         // Set the normal
00468         vertex.setNormal(n);
00469 
00470         vertex.setPoint( v0 );
00471         shapeVertex(&vertex);
00472         vertex.setPoint( v1 );
00473         shapeVertex(&vertex);
00474         vertex.setPoint( v2 );
00475         shapeVertex(&vertex);
00476       }
00477       endShape();
00478     } else {
00479       // Create the information when moving over or picking into the scene
00480       SoPrimitiveVertex vertex;
00481       SoPointDetail pointDetail;
00482       SoFaceDetail faceDetail;
00483 
00484       vertex.setDetail(&pointDetail);
00485 
00486       beginShape(action, TRIANGLES, &faceDetail);
00487       for ( MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it )
00488       {
00489         const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[0]];
00490         const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[1]];
00491         const MeshCore::MeshPoint& v2 = rPoints[it->_aulPoints[2]];
00492 
00493         // Calculate the normal n = (v1-v0)x(v2-v0)
00494         SbVec3f n;
00495         n[0] = (v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y);
00496         n[1] = (v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z);
00497         n[2] = (v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x);
00498 
00499         // Set the normal
00500         vertex.setNormal(n);
00501 
00502         // Vertex 0
00503         pointDetail.setCoordinateIndex(it->_aulPoints[0]);
00504         vertex.setPoint(sbvec3f(v0));
00505         shapeVertex(&vertex);
00506 
00507         // Vertex 1
00508         pointDetail.setCoordinateIndex(it->_aulPoints[1]);
00509         vertex.setPoint(sbvec3f(v1));
00510         shapeVertex(&vertex);
00511 
00512         // Vertex 2
00513         pointDetail.setCoordinateIndex(it->_aulPoints[2]);
00514         vertex.setPoint(sbvec3f(v2));
00515         shapeVertex(&vertex);
00516 
00517         // Increment for the next face
00518         faceDetail.incFaceIndex();
00519       }
00520 
00521       endShape();
00522     }
00523   }
00524 }
00525 
00531 SoDetail * SoFCMeshNode::createTriangleDetail(SoRayPickAction * action,
00532                                               const SoPrimitiveVertex * v1,
00533                                               const SoPrimitiveVertex * v2,
00534                                               const SoPrimitiveVertex * v3,
00535                                               SoPickedPoint * pp)
00536 {
00537   if ( this->MaximumTriangles < countTriangles() ) {
00538     return 0;
00539   } else {
00540     SoDetail* detail = inherited::createTriangleDetail(action, v1, v2, v3, pp);
00541     return detail;
00542   }
00543 }
00544 
00548 void SoFCMeshNode::computeBBox(SoAction *action, SbBox3f &box, SbVec3f &center)
00549 {
00550   // Get the bbox directly from the mesh kernel
00551   if (countTriangles() > 0) {
00552     const Base::BoundBox3f& cBox = _mesh->getKernel().GetBoundBox();
00553     box.setBounds(SbVec3f(cBox.MinX,cBox.MinY,cBox.MinZ),
00554                   SbVec3f(cBox.MaxX,cBox.MaxY,cBox.MaxZ));
00555     Base::Vector3f mid = cBox.CalcCenter();
00556     center.setValue(mid.x,mid.y,mid.z);
00557   }
00558   else {
00559     box.setBounds(SbVec3f(0,0,0), SbVec3f(0,0,0));
00560     center.setValue(0.0f,0.0f,0.0f);
00561   }
00562 }
00563 
00567 void SoFCMeshNode::getPrimitiveCount(SoGetPrimitiveCountAction * action)
00568 {
00569   if (!this->shouldPrimitiveCount(action)) return;
00570   action->addNumTriangles(countTriangles());
00571 }
00572 
00576 unsigned int SoFCMeshNode::countTriangles() const
00577 {
00578   return (_mesh ? _mesh->countFacets() : 0);
00579 }
00580 
00584 void SoFCMeshNode::write( SoWriteAction* action ) 
00585 { 
00586   SoOutput * out = action->getOutput();
00587 
00588   if (out->getStage() == SoOutput::COUNT_REFS) {
00589     this->addWriteReference(out, FALSE);
00590   }
00591   else if (out->getStage() == SoOutput::WRITE) {
00592     const MeshCore::MeshPointArray& rPoints = _mesh->getKernel().GetPoints();
00593     const MeshCore::MeshFacetArray& rFacets = _mesh->getKernel().GetFacets();
00594     if (this->writeHeader(out, FALSE, FALSE)) return;
00595     point.setNum(rPoints.size());
00596     unsigned int pos=0;
00597     for (MeshCore::MeshPointArray::_TConstIterator cP=rPoints.begin(); cP!=rPoints.end(); ++cP)
00598       point.set1Value(pos++,cP->x,cP->y,cP->z);
00599     coordIndex.setNum(3*rFacets.size());
00600     pos=0;
00601     for (MeshCore::MeshFacetArray::_TConstIterator cF=rFacets.begin(); cF!=rFacets.end(); ++cF){
00602       coordIndex.set1Value(pos++,cF->_aulPoints[0]);
00603       coordIndex.set1Value(pos++,cF->_aulPoints[1]);
00604       coordIndex.set1Value(pos++,cF->_aulPoints[2]);
00605     }
00606     this->getFieldData()->write(out, this);
00607     this->writeFooter(out);
00608     point.deleteValues(0);
00609     coordIndex.deleteValues(0);
00610   }
00611 }
00612 
00616 SbBool SoFCMeshNode::readInstance( SoInput* in, unsigned short  flags )
00617 {
00618   SbBool ret = inherited::readInstance(in, flags);
00619 
00620   MeshCore::MeshPointArray cPoints;
00621   cPoints.resize(point.getNum());
00622   for (int i=0; i<point.getNum(); ++i) {
00623     const SbVec3f& pt = point[i];
00624     cPoints[i].Set(pt[0],pt[1],pt[2]);
00625   }
00626 
00627   MeshCore::MeshFacetArray cFacets;
00628   cFacets.resize(coordIndex.getNum()/3);
00629   unsigned long k=0;
00630   for (int j=0; j<coordIndex.getNum(); ++k) {
00631     cFacets[k]._aulPoints[0] = coordIndex[j++];
00632     cFacets[k]._aulPoints[1] = coordIndex[j++];
00633     cFacets[k]._aulPoints[2] = coordIndex[j++];
00634   }
00635 
00636   point.deleteValues(0);
00637   coordIndex.deleteValues(0);
00638 
00639   MeshCore::MeshKernel kernel;
00640   kernel.Adopt(cPoints, cFacets, true);
00641   _mesh = new Mesh::MeshObject(kernel);
00642 
00643   return ret;
00644 }
00645 
00646 // -------------------------------------------------------
00647 
00648 SO_NODE_SOURCE(SoFCMeshOpenEdge);
00649 
00650 void SoFCMeshOpenEdge::initClass()
00651 {
00652   SO_NODE_INIT_CLASS(SoFCMeshOpenEdge, SoShape, "Shape");
00653 }
00654 
00655 SoFCMeshOpenEdge::SoFCMeshOpenEdge() : _mesh(0)
00656 {
00657   SO_NODE_CONSTRUCTOR(SoFCMeshOpenEdge);
00658 }
00659 
00663 void SoFCMeshOpenEdge::setMesh(const Mesh::MeshObject* mesh)
00664 { 
00665   _mesh = mesh; 
00666 }
00667 
00671 void SoFCMeshOpenEdge::GLRender(SoGLRenderAction *action)
00672 {
00673   if (_mesh && shouldGLRender(action))
00674   {
00675     SoState*  state = action->getState();
00676 
00677     SoMaterialBundle mb(action);
00678     SoTextureCoordinateBundle tb(action, TRUE, FALSE);
00679     SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);
00680     mb.sendFirst();  // make sure we have the correct material
00681 
00682     drawLines();
00683 
00684     // Disable caching for this node
00685     SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE);
00686   }
00687 }
00688 
00692 void SoFCMeshOpenEdge::drawLines() const
00693 {
00694   // Use the data structure directly and not through MeshFacetIterator as this
00695   // class is quite slowly (at least for rendering)
00696   const MeshCore::MeshPointArray& rPoints = _mesh->getKernel().GetPoints();
00697   const MeshCore::MeshFacetArray& rFacets = _mesh->getKernel().GetFacets();
00698 
00699   // When rendering open edges use the given line width * 3 
00700   GLfloat lineWidth;
00701   glGetFloatv(GL_LINE_WIDTH, &lineWidth);
00702   glLineWidth(3.0f*lineWidth);
00703 
00704 
00705   glBegin(GL_LINES);
00706   for ( MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it ) {
00707     for ( int i=0; i<3; i++ ) {
00708       if ( it->_aulNeighbours[i] == ULONG_MAX ) {
00709         glVertex(rPoints[it->_aulPoints[i]]);
00710         glVertex(rPoints[it->_aulPoints[(i+1)%3]]);
00711       }
00712     }
00713   }
00714 
00715   glEnd();
00716 }
00717 
00718 void SoFCMeshOpenEdge::generatePrimitives(SoAction* action)
00719 {
00720   // do not create primitive information as an SoFCMeshNode should already be used that delivers the information
00721 }
00722 
00726 void SoFCMeshOpenEdge::computeBBox(SoAction *action, SbBox3f &box, SbVec3f &center)
00727 {
00728   // Get the bbox directly from the mesh kernel
00729   if (_mesh) {
00730     const Base::BoundBox3f& cBox = _mesh->getKernel().GetBoundBox();
00731     box.setBounds(SbVec3f(cBox.MinX,cBox.MinY,cBox.MinZ),
00732                               SbVec3f(cBox.MaxX,cBox.MaxY,cBox.MaxZ));
00733     Base::Vector3f mid = cBox.CalcCenter();
00734     center.setValue(mid.x,mid.y,mid.z);
00735   }
00736   else {
00737     box.setBounds(SbVec3f(0,0,0), SbVec3f(0,0,0));
00738     center.setValue(0.0f,0.0f,0.0f);
00739   }
00740 }
00741 
00745 void SoFCMeshOpenEdge::getPrimitiveCount(SoGetPrimitiveCountAction * action)
00746 {
00747   if (!this->shouldPrimitiveCount(action)) return;
00748   
00749   // Count number of open edges first
00750   int ctEdges=0;
00751 
00752   const MeshCore::MeshFacetArray& rFaces = _mesh->getKernel().GetFacets();
00753   for ( MeshCore::MeshFacetArray::_TConstIterator jt = rFaces.begin(); jt != rFaces.end(); ++jt ) {
00754     for ( int i=0; i<3; i++ ) {
00755       if ( jt->_aulNeighbours[i] == ULONG_MAX ) {
00756         ctEdges++;
00757       }
00758     }
00759   }
00760 
00761   action->addNumLines(ctEdges);
00762 }

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