SoFCMeshFaceSet.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/SoCallbackAction.h>
00039 # include <Inventor/actions/SoGLRenderAction.h>
00040 # include <Inventor/actions/SoGetBoundingBoxAction.h>
00041 # include <Inventor/actions/SoGetPrimitiveCountAction.h>
00042 # include <Inventor/actions/SoPickAction.h>
00043 # include <Inventor/actions/SoRayPickAction.h>
00044 # include <Inventor/actions/SoWriteAction.h>
00045 # include <Inventor/bundles/SoMaterialBundle.h>
00046 # include <Inventor/bundles/SoTextureCoordinateBundle.h>
00047 # include <Inventor/caches/SoBoundingBoxCache.h>
00048 # include <Inventor/details/SoFaceDetail.h>
00049 # include <Inventor/details/SoLineDetail.h>
00050 # include <Inventor/details/SoPointDetail.h>
00051 # include <Inventor/elements/SoGLCacheContextElement.h>
00052 # include <Inventor/elements/SoLazyElement.h>
00053 # include <Inventor/elements/SoLightModelElement.h>
00054 # include <Inventor/misc/SoState.h>
00055 # include <Inventor/errors/SoReadError.h>
00056 #endif
00057 
00058 #include <Inventor/caches/SoBoundingBoxCache.h>
00059 
00060 #include <Base/Console.h>
00061 #include <Base/Exception.h>
00062 #include <Gui/SoFCInteractiveElement.h>
00063 #include <Mod/Mesh/App/Core/Elements.h>
00064 #include <Mod/Mesh/App/Core/Grid.h>
00065 #include <Mod/Mesh/App/Core/Algorithm.h>
00066 #include <Mod/Mesh/App/Core/MeshIO.h>
00067 #include "SoFCMeshFaceSet.h"
00068 #include "SoFCMeshVertex.h"
00069 
00070 using namespace MeshGui;
00071 
00072 
00073 // Defines all required member variables and functions for a
00074 // single-value field
00075 SO_SFIELD_SOURCE(SoSFMeshFacetArray, MeshCore::MeshFacetArray*, MeshCore::MeshFacetArray*);
00076 
00077 
00078 void SoSFMeshFacetArray::initClass()
00079 {
00080    // This macro takes the name of the class and the name of the
00081    // parent class
00082    SO_SFIELD_INIT_CLASS(SoSFMeshFacetArray, SoSField);
00083 }
00084 
00085 void SoSFMeshFacetArray::setValue(const MeshCore::MeshFacetArray& p)
00086 {
00087   SoSFMeshFacetArray::setValue(const_cast<MeshCore::MeshFacetArray*>(&p));
00088 }
00089 
00090 // This reads the value of a field from a file. It returns FALSE if the value could not be read
00091 // successfully.
00092 SbBool SoSFMeshFacetArray::readValue(SoInput *in)
00093 {
00094   // This macro is convenient for reading with error detection.
00095 #define READ_VAL(val) \
00096   if (!in->read(val)) { \
00097     SoReadError::post(in, "Premature end of file"); \
00098     return FALSE; \
00099   }
00100 
00101   value = new MeshCore::MeshFacetArray();
00102 
00103   // ** Binary format ******************************************************
00104   if (in->isBinary()) {
00105     int numtoread;
00106     READ_VAL(numtoread);
00107 
00108     // Sanity checking on the value, to avoid barfing on corrupt
00109     // files.
00110     if (numtoread < 0) {
00111       SoReadError::post(in, "invalid number of values in field: %d",
00112                         numtoread);
00113       return FALSE;
00114     }
00115 
00116     value->resize(numtoread);
00117     if (!this->readBinaryValues(in, numtoread)) { return FALSE; }
00118   }
00119 
00120   // ** ASCII format *******************************************************
00121   else {
00122     char c;
00123     READ_VAL(c);
00124     if (c == '[') {
00125       unsigned long currentidx = 0;
00126 
00127       READ_VAL(c);
00128       if (c == ']') {
00129         // Zero values -- done. :^)
00130       }
00131       else {
00132         in->putBack(c);
00133 
00134         while (TRUE) {
00135           // makeRoom() makes sure the allocation strategy is decent.
00136           if (currentidx >= value->size()) value->resize(currentidx + 1);
00137 
00138           if (!this->read1Value(in, currentidx++)) return FALSE;
00139 
00140           READ_VAL(c);
00141           if (c == ',') { READ_VAL(c); } // Treat trailing comma as whitespace.
00142 
00143           // That was the last array element, we're done.
00144           if (c == ']') { break; }
00145 
00146           if (c == '}') {
00147             SoReadError::post(in, "Premature end of array, got '%c'", c);
00148             return FALSE;
00149           }
00150 
00151           in->putBack(c);
00152         }
00153       }
00154 
00155       // Fit array to number of items.
00156       value->resize(currentidx);
00157     }
00158     else {
00159       in->putBack(c);
00160       value->resize(1);
00161       if (!this->read1Value(in, 0)) return FALSE;
00162     }
00163   }
00164 
00165 #undef READ_VAL
00166 
00167   // Create a dummy point array
00168   MeshCore::MeshPointArray vertex;
00169   MeshCore::MeshKernel mesh;
00170   // Let the mesh kernel restore the neighbourhoods of the facets for us
00171   mesh.Adopt(vertex, *value, true);
00172   // Give us back the face data 
00173   mesh.Adopt(vertex, *value, false);
00174 
00175   // We need to trigger the notification chain here, as this function
00176   // can be used on a node in a scene graph in any state -- not only
00177   // during initial scene graph import.
00178   this->valueChanged();
00179   
00180   return TRUE;
00181 }
00182 
00183 SbBool SoSFMeshFacetArray::readBinaryValues(SoInput * in, unsigned long numarg)
00184 {
00185   assert(in->isBinary());
00186   assert(numarg >= 0);
00187 
00188   for (unsigned long i=0; i < numarg; i++) if (!this->read1Value(in, i)) return FALSE;
00189   return TRUE;
00190 }
00191 
00192 SbBool SoSFMeshFacetArray::read1Value(SoInput * in, unsigned long idx)
00193 {
00194   assert(idx < value->size());
00195   MeshCore::MeshFacet& v = (*value)[idx];
00196   int32_t p0, p1, p2;
00197   SbBool ret = (in->read(p0) && in->read(p1) && in->read(p2));
00198   if ( ret ) {
00199     v._aulPoints[0] = p0;
00200     v._aulPoints[1] = p1;
00201     v._aulPoints[2] = p2;
00202   }
00203 
00204   return ret;
00205 }
00206 
00207 int SoSFMeshFacetArray::getNumValuesPerLine() const
00208 {
00209   return 2;
00210 }
00211 
00212 // This writes the value of a field to a file.
00213 void SoSFMeshFacetArray::writeValue(SoOutput *out) const
00214 {
00215   if (out->isBinary()) {
00216     this->writeBinaryValues(out);
00217     return;
00218   }
00219 
00220   const unsigned long count = value->size();
00221   if ((count > 1) || (count == 0)) out->write("[ ");
00222 
00223   out->incrementIndent();
00224 
00225   for (unsigned long i=0; i < count; i++) {
00226     this->write1Value(out, i);
00227 
00228     if (i != count-1) {
00229       if (((i+1) % this->getNumValuesPerLine()) == 0) {
00230         out->write(",\n");
00231         out->indent();
00232         // for alignment
00233         out->write("  ");
00234       }
00235       else {
00236         out->write(", ");
00237       }
00238     }
00239   }
00240   if ((count > 1) || (count == 0)) out->write(" ]");
00241 
00242   out->decrementIndent();
00243 }
00244 
00245 void SoSFMeshFacetArray::writeBinaryValues(SoOutput * out) const
00246 {
00247   assert(out->isBinary());
00248 
00249   const unsigned int count = (unsigned int)value->size();
00250   out->write(count);
00251   for (unsigned int i=0; i < count; i++) this->write1Value(out, i);
00252 }
00253 
00254 void SoSFMeshFacetArray::write1Value(SoOutput * out, unsigned long idx) const
00255 {
00256   const MeshCore::MeshFacet& v = (*value)[idx];
00257   out->write((int32_t)(v._aulPoints[0]));
00258   if (!out->isBinary()) out->write(' ');
00259   out->write((int32_t)(v._aulPoints[1]));
00260   if (!out->isBinary()) out->write(' ');
00261   out->write((int32_t)(v._aulPoints[2]));
00262 }
00263 
00264 // -------------------------------------------------------
00265 
00266 SO_ELEMENT_SOURCE(SoFCMeshFacetElement);
00267 
00268 void SoFCMeshFacetElement::initClass()
00269 {
00270    SO_ELEMENT_INIT_CLASS(SoFCMeshFacetElement, inherited);
00271 }
00272 
00273 void SoFCMeshFacetElement::init(SoState * state)
00274 {
00275   inherited::init(state);
00276   this->coordIndex = 0;
00277 }
00278 
00279 SoFCMeshFacetElement::~SoFCMeshFacetElement()
00280 {
00281 }
00282 
00283 void SoFCMeshFacetElement::set(SoState * const state, SoNode * const node, const MeshCore::MeshFacetArray * const coords)
00284 {
00285   SoFCMeshFacetElement * elem = (SoFCMeshFacetElement *)
00286     SoReplacedElement::getElement(state, classStackIndex, node);
00287   if (elem) {
00288     elem->coordIndex = coords;
00289     elem->nodeId = node->getNodeId();
00290   }
00291 }
00292 
00293 const MeshCore::MeshFacetArray * SoFCMeshFacetElement::get(SoState * const state)
00294 {
00295   return SoFCMeshFacetElement::getInstance(state)->coordIndex;
00296 }
00297 
00298 const SoFCMeshFacetElement * SoFCMeshFacetElement::getInstance(SoState * state)
00299 {
00300   return (const SoFCMeshFacetElement *) SoElement::getConstElement(state, classStackIndex);
00301 }
00302 
00303 void SoFCMeshFacetElement::print(FILE * /* file */) const
00304 {
00305 }
00306 
00307 // -------------------------------------------------------
00308 
00309 SO_NODE_SOURCE(SoFCMeshFacet);
00310 
00314 SoFCMeshFacet::SoFCMeshFacet(void)
00315 {
00316   SO_NODE_CONSTRUCTOR(SoFCMeshFacet);
00317 
00318   SO_NODE_ADD_FIELD(coordIndex, (0));
00319 }
00320 
00324 SoFCMeshFacet::~SoFCMeshFacet()
00325 {
00326 }
00327 
00328 // Doc from superclass.
00329 void SoFCMeshFacet::initClass(void)
00330 {
00331   SO_NODE_INIT_CLASS(SoFCMeshFacet, SoNode, "Node");
00332 
00333   SO_ENABLE(SoGetBoundingBoxAction, SoFCMeshFacetElement);
00334   SO_ENABLE(SoGLRenderAction, SoFCMeshFacetElement);
00335   SO_ENABLE(SoPickAction, SoFCMeshFacetElement);
00336   SO_ENABLE(SoCallbackAction, SoFCMeshFacetElement);
00337   SO_ENABLE(SoGetPrimitiveCountAction, SoFCMeshFacetElement);
00338 }
00339 
00340 // Doc from superclass.
00341 void SoFCMeshFacet::doAction(SoAction * action)
00342 {
00343   SoFCMeshFacetElement::set(action->getState(), this, coordIndex.getValue());
00344 }
00345 
00346 // Doc from superclass.
00347 void SoFCMeshFacet::GLRender(SoGLRenderAction * action)
00348 {
00349   SoFCMeshFacet::doAction(action);
00350 }
00351 
00352 // Doc from superclass.
00353 void SoFCMeshFacet::callback(SoCallbackAction * action)
00354 {
00355   SoFCMeshFacet::doAction(action);
00356 }
00357 
00358 // Doc from superclass.
00359 void SoFCMeshFacet::pick(SoPickAction * action)
00360 {
00361   SoFCMeshFacet::doAction(action);
00362 }
00363 
00364 // Doc from superclass.
00365 void SoFCMeshFacet::getBoundingBox(SoGetBoundingBoxAction * action)
00366 {
00367   SoFCMeshFacet::doAction(action);
00368 }
00369 
00370 // Doc from superclass.
00371 void SoFCMeshFacet::getPrimitiveCount(SoGetPrimitiveCountAction * action)
00372 {
00373   SoFCMeshFacet::doAction(action);
00374 }
00375 
00376 // -------------------------------------------------------
00377 
00395 // Helper functions: draw vertices
00396 inline void glVertex(const MeshCore::MeshPoint& _v)  
00397 { 
00398   float v[3];
00399   v[0]=_v.x; v[1]=_v.y;v[2]=_v.z;
00400   glVertex3fv(v); 
00401 }
00402 
00403 // Helper functions: draw normal
00404 inline void glNormal(const Base::Vector3f& _n)
00405 { 
00406   float n[3];
00407   n[0]=_n.x; n[1]=_n.y;n[2]=_n.z;
00408   glNormal3fv(n); 
00409 }
00410 
00411 // Helper functions: draw normal
00412 inline void glNormal(float* n)
00413 { 
00414   glNormal3fv(n); 
00415 }
00416 
00417 // Helper function: convert Vec to SbVec3f
00418 inline SbVec3f sbvec3f(const Base::Vector3f& _v) {
00419   return SbVec3f(_v.x, _v.y, _v.z); 
00420 }
00421 
00422 SO_NODE_SOURCE(SoFCMeshFaceSet);
00423 
00424 void SoFCMeshFaceSet::initClass()
00425 {
00426   SO_NODE_INIT_CLASS(SoFCMeshFaceSet, SoShape, "Shape");
00427 }
00428 
00429 SoFCMeshFaceSet::SoFCMeshFaceSet() : MaximumTriangles(100000), meshChanged(true)
00430 {
00431   SO_NODE_CONSTRUCTOR(SoFCMeshFaceSet);
00432 }
00433 
00434 void SoFCMeshFaceSet::notify(SoNotList * node)
00435 {
00436   SoShape::notify(node);
00437   meshChanged = true;
00438 }
00439 
00452 void SoFCMeshFaceSet::createProxyModel(const MeshCore::MeshPointArray* rPoints, const MeshCore::MeshFacetArray* rFaces, SbBool simplest)
00453 {
00454   Base::BoundBox3f cBox;
00455   for ( MeshCore::MeshPointArray::_TConstIterator it = rPoints->begin(); it != rPoints->end(); ++it )
00456     cBox &= (*it);
00457 
00458   if ( simplest ) {
00459     int triangles[36] = {
00460       0,1,2,0,2,3,
00461       0,1,5,0,5,4,
00462       0,4,7,0,7,3,
00463       6,7,4,6,4,5,
00464       6,2,3,6,3,7,
00465       6,1,2,6,5,1
00466     };
00467     SbVec3f points[8] = {
00468       SbVec3f(cBox.MinX,cBox.MinY,cBox.MinZ),
00469       SbVec3f(cBox.MaxX,cBox.MinY,cBox.MinZ),
00470       SbVec3f(cBox.MaxX,cBox.MaxY,cBox.MinZ),
00471       SbVec3f(cBox.MinX,cBox.MaxY,cBox.MinZ),
00472       SbVec3f(cBox.MinX,cBox.MinY,cBox.MaxZ),
00473       SbVec3f(cBox.MaxX,cBox.MinY,cBox.MaxZ),
00474       SbVec3f(cBox.MaxX,cBox.MaxY,cBox.MaxZ),
00475       SbVec3f(cBox.MinX,cBox.MaxY,cBox.MaxZ)
00476     };
00477 
00478     coordIndex.setValues(0,36,triangles);
00479     point.setValues (0,8,points);
00480   } else {
00481 
00482     // takes the point and facet arrays under it's wings for a short moment
00483     MeshCore::MeshKernel mesh;
00484     mesh.Assign(*rPoints, *rFaces,false);
00485 
00486     // Check the boundings and the average edge length
00487     float fAvgLen = 5.0f * MeshCore::MeshAlgorithm(mesh).GetAverageEdgeLength();
00488 
00489     // create maximum 50 grids in each direction 
00490     fAvgLen = std::max<float>(fAvgLen, (cBox.MaxX-cBox.MinX)/50.0f);
00491     fAvgLen = std::max<float>(fAvgLen, (cBox.MaxY-cBox.MinY)/50.0f);
00492     fAvgLen = std::max<float>(fAvgLen, (cBox.MaxZ-cBox.MinZ)/50.0f);
00493 
00494     MeshCore::MeshGeomFacet face;
00495     std::vector<MeshCore::MeshGeomFacet> facets;
00496 
00497     MeshCore::MeshPointGrid cGrid(mesh, fAvgLen);
00498     unsigned long ulMaxX, ulMaxY, ulMaxZ;
00499     cGrid.GetCtGrids(ulMaxX, ulMaxY, ulMaxZ);
00500     MeshCore::MeshGridIterator cIter(cGrid);
00501 
00502     for ( cIter.Init(); cIter.More(); cIter.Next() ) {
00503       if ( cIter.GetCtElements() > 0 ) {
00504         unsigned long ulX, ulY, ulZ;
00505         cIter.GetGridPos(ulX, ulY, ulZ);
00506         Base::BoundBox3f cBox = cIter.GetBoundBox();
00507 
00508         if ( ulX == 0 || (ulX-1 >= 0 && cGrid.GetCtElements(ulX-1,ulY, ulZ) == 0) ) {
00509           face._aclPoints[0].Set(cBox.MinX,cBox.MinY,cBox.MinZ);
00510           face._aclPoints[1].Set(cBox.MinX,cBox.MinY,cBox.MaxZ);
00511           face._aclPoints[2].Set(cBox.MinX,cBox.MaxY,cBox.MinZ);
00512           facets.push_back(face);
00513           face._aclPoints[0].Set(cBox.MinX,cBox.MaxY,cBox.MaxZ);
00514           face._aclPoints[1].Set(cBox.MinX,cBox.MaxY,cBox.MinZ);
00515           face._aclPoints[2].Set(cBox.MinX,cBox.MinY,cBox.MaxZ);
00516           facets.push_back(face);
00517         }
00518         if ( ulX+1 == ulMaxX || (ulX+1 < ulMaxX && cGrid.GetCtElements(ulX+1,ulY, ulZ) == 0) ) {
00519           face._aclPoints[0].Set(cBox.MaxX,cBox.MinY,cBox.MinZ);
00520           face._aclPoints[1].Set(cBox.MaxX,cBox.MaxY,cBox.MinZ);
00521           face._aclPoints[2].Set(cBox.MaxX,cBox.MinY,cBox.MaxZ);
00522           facets.push_back(face);
00523           face._aclPoints[0].Set(cBox.MaxX,cBox.MaxY,cBox.MaxZ);
00524           face._aclPoints[1].Set(cBox.MaxX,cBox.MinY,cBox.MaxZ);
00525           face._aclPoints[2].Set(cBox.MaxX,cBox.MaxY,cBox.MinZ);
00526           facets.push_back(face);
00527         }
00528         if ( ulY == 0 || (ulY-1 >= 0 && cGrid.GetCtElements(ulX,ulY-1, ulZ) == 0) ) {
00529           face._aclPoints[0].Set(cBox.MinX,cBox.MinY,cBox.MaxZ);
00530           face._aclPoints[1].Set(cBox.MinX,cBox.MinY,cBox.MinZ);
00531           face._aclPoints[2].Set(cBox.MaxX,cBox.MinY,cBox.MaxZ);
00532           facets.push_back(face);
00533           face._aclPoints[0].Set(cBox.MaxX,cBox.MinY,cBox.MinZ);
00534           face._aclPoints[1].Set(cBox.MaxX,cBox.MinY,cBox.MaxZ);
00535           face._aclPoints[2].Set(cBox.MinX,cBox.MinY,cBox.MinZ);
00536           facets.push_back(face);
00537         }
00538         if ( ulY+1 == ulMaxY || (ulY+1 < ulMaxY && cGrid.GetCtElements(ulX,ulY+1, ulZ) == 0) ) {
00539           face._aclPoints[0].Set(cBox.MaxX,cBox.MaxY,cBox.MinZ);
00540           face._aclPoints[1].Set(cBox.MinX,cBox.MaxY,cBox.MinZ);
00541           face._aclPoints[2].Set(cBox.MaxX,cBox.MaxY,cBox.MaxZ);
00542           facets.push_back(face);
00543           face._aclPoints[0].Set(cBox.MinX,cBox.MaxY,cBox.MaxZ);
00544           face._aclPoints[1].Set(cBox.MaxX,cBox.MaxY,cBox.MaxZ);
00545           face._aclPoints[2].Set(cBox.MinX,cBox.MaxY,cBox.MinZ);
00546           facets.push_back(face);
00547         }
00548         if ( ulZ == 0 || (ulZ-1 >= 0 && cGrid.GetCtElements(ulX,ulY, ulZ-1) == 0) ) {
00549           face._aclPoints[0].Set(cBox.MaxX,cBox.MinY,cBox.MinZ);
00550           face._aclPoints[1].Set(cBox.MinX,cBox.MinY,cBox.MinZ);
00551           face._aclPoints[2].Set(cBox.MaxX,cBox.MaxY,cBox.MinZ);
00552           facets.push_back(face);
00553           face._aclPoints[0].Set(cBox.MinX,cBox.MaxY,cBox.MinZ);
00554           face._aclPoints[1].Set(cBox.MaxX,cBox.MaxY,cBox.MinZ);
00555           face._aclPoints[2].Set(cBox.MinX,cBox.MinY,cBox.MinZ);
00556           facets.push_back(face);
00557         }
00558         if ( ulZ+1 == ulMaxZ || (ulZ+1 < ulMaxZ && cGrid.GetCtElements(ulX,ulY, ulZ+1) == 0) ) {
00559           face._aclPoints[0].Set(cBox.MaxX,cBox.MinY,cBox.MaxZ);
00560           face._aclPoints[1].Set(cBox.MaxX,cBox.MaxY,cBox.MaxZ);
00561           face._aclPoints[2].Set(cBox.MinX,cBox.MinY,cBox.MaxZ);
00562           facets.push_back(face);
00563           face._aclPoints[0].Set(cBox.MinX,cBox.MaxY,cBox.MaxZ);
00564           face._aclPoints[1].Set(cBox.MinX,cBox.MinY,cBox.MaxZ);
00565           face._aclPoints[2].Set(cBox.MaxX,cBox.MaxY,cBox.MaxZ);
00566           facets.push_back(face);
00567         }
00568       }
00569     }
00570 
00571     MeshCore::MeshKernel kernel; kernel = facets;
00572     const MeshCore::MeshPointArray& rPoints = kernel.GetPoints();
00573     const MeshCore::MeshFacetArray& rFacets = kernel.GetFacets();
00574 
00575     point.enableNotify(false);
00576     point.setNum(rPoints.size());
00577     unsigned int pos=0;
00578     for (MeshCore::MeshPointArray::_TConstIterator cP=rPoints.begin(); cP!=rPoints.end(); ++cP)
00579       point.set1Value(pos++,cP->x,cP->y,cP->z);
00580     point.enableNotify(true);
00581 
00582     coordIndex.enableNotify(false);
00583     coordIndex.setNum(3*rFacets.size());
00584     pos=0;
00585     for (MeshCore::MeshFacetArray::_TConstIterator cF=rFacets.begin(); cF!=rFacets.end(); ++cF){
00586       coordIndex.set1Value(pos++,cF->_aulPoints[0]);
00587       coordIndex.set1Value(pos++,cF->_aulPoints[1]);
00588       coordIndex.set1Value(pos++,cF->_aulPoints[2]);
00589     }
00590     coordIndex.enableNotify(true);
00591 
00592     point.touch();
00593     coordIndex.touch();
00594 
00595 #ifdef FC_DEBUG
00596     std::ofstream str( "bbox.stl", std::ios::out | std::ios::binary );
00597     MeshCore::MeshOutput aWriter(kernel);
00598     aWriter.SaveBinarySTL( str );
00599 #endif
00600   }
00601 }
00602 
00606 void SoFCMeshFaceSet::GLRender(SoGLRenderAction *action)
00607 {
00608   if (shouldGLRender(action))
00609   {
00610     SoState*  state = action->getState();
00611 
00612     SbBool mode = Gui::SoFCInteractiveElement::get(state);
00613     const MeshCore::MeshPointArray * coords = SoFCMeshVertexElement::get(state);
00614     const MeshCore::MeshFacetArray * index = SoFCMeshFacetElement::get(state);
00615 
00616     Binding mbind = this->findMaterialBinding(state);
00617 
00618     SoMaterialBundle mb(action);
00619     //SoTextureCoordinateBundle tb(action, true, false);
00620 
00621     SbBool needNormals = !mb.isColorOnly()/* || tb.isFunction()*/;
00622     mb.sendFirst();  // make sure we have the correct material
00623     
00624     SbBool ccw = TRUE;
00625     if (SoShapeHintsElement::getVertexOrdering(state) == SoShapeHintsElement::CLOCKWISE) 
00626       ccw = FALSE;
00627 
00628     if ( mode == false || index->size() <= this->MaximumTriangles ) {
00629       if ( mbind != OVERALL )
00630         drawFaces(coords, index, &mb, mbind, needNormals, ccw);
00631       else
00632         drawFaces(coords, index, 0, mbind, needNormals, ccw);
00633     } else {
00634       drawPoints(coords, index, needNormals, ccw);
00635     }
00636 
00637     // Disable caching for this node
00638     SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE);
00639   }
00640 }
00641 
00645 SoFCMeshFaceSet::Binding SoFCMeshFaceSet::findMaterialBinding(SoState * const state) const
00646 {
00647   Binding binding = OVERALL;
00648   SoMaterialBindingElement::Binding matbind = SoMaterialBindingElement::get(state);
00649 
00650   switch (matbind) {
00651   case SoMaterialBindingElement::OVERALL:
00652     binding = OVERALL;
00653     break;
00654   case SoMaterialBindingElement::PER_VERTEX:
00655     binding = PER_VERTEX_INDEXED;
00656     break;
00657   case SoMaterialBindingElement::PER_VERTEX_INDEXED:
00658     binding = PER_VERTEX_INDEXED;
00659     break;
00660   case SoMaterialBindingElement::PER_PART:
00661   case SoMaterialBindingElement::PER_FACE:
00662     binding = PER_FACE_INDEXED;
00663     break;
00664   case SoMaterialBindingElement::PER_PART_INDEXED:
00665   case SoMaterialBindingElement::PER_FACE_INDEXED:
00666     binding = PER_FACE_INDEXED;
00667     break;
00668   default:
00669     break;
00670   }
00671   return binding;
00672 }
00673 
00679 void SoFCMeshFaceSet::drawFaces(const MeshCore::MeshPointArray * rPoints, const MeshCore::MeshFacetArray* rFacets, 
00680                                 SoMaterialBundle* mb, Binding bind, SbBool needNormals, SbBool ccw) const
00681 {
00682   bool perVertex = (mb && bind == PER_VERTEX_INDEXED);
00683   bool perFace = (mb && bind == PER_FACE_INDEXED);
00684 
00685   if (needNormals)
00686   {
00687     glBegin(GL_TRIANGLES);
00688     if ( ccw ) {
00689       // counterclockwise ordering
00690       for ( MeshCore::MeshFacetArray::_TConstIterator it = rFacets->begin(); it != rFacets->end(); ++it )
00691       {
00692         const MeshCore::MeshPoint& v0 = (*rPoints)[it->_aulPoints[0]];
00693         const MeshCore::MeshPoint& v1 = (*rPoints)[it->_aulPoints[1]];
00694         const MeshCore::MeshPoint& v2 = (*rPoints)[it->_aulPoints[2]];
00695 
00696         // Calculate the normal n = (v1-v0)x(v2-v0)
00697         float n[3];
00698         n[0] = (v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y);
00699         n[1] = (v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z);
00700         n[2] = (v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x);
00701     
00702         if(perFace)
00703         mb->send(it-rFacets->begin(), TRUE);
00704         glNormal(n);
00705         if(perVertex)
00706         mb->send(it->_aulPoints[0], TRUE);
00707         glVertex(v0);
00708         if(perVertex)
00709         mb->send(it->_aulPoints[1], TRUE);
00710         glVertex(v1);
00711         if(perVertex)
00712         mb->send(it->_aulPoints[2], TRUE);
00713         glVertex(v2);
00714       }
00715     } else {
00716       // clockwise ordering
00717       for ( MeshCore::MeshFacetArray::_TConstIterator it = rFacets->begin(); it != rFacets->end(); ++it )
00718       {
00719         const MeshCore::MeshPoint& v0 = (*rPoints)[it->_aulPoints[0]];
00720         const MeshCore::MeshPoint& v1 = (*rPoints)[it->_aulPoints[1]];
00721         const MeshCore::MeshPoint& v2 = (*rPoints)[it->_aulPoints[2]];
00722 
00723         // Calculate the normal n = -(v1-v0)x(v2-v0)
00724         float n[3];
00725         n[0] = -((v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y));
00726         n[1] = -((v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z));
00727         n[2] = -((v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x));
00728     
00729         glNormal(n);
00730         glVertex(v0);
00731         glVertex(v1);
00732         glVertex(v2);
00733       }
00734     }
00735     glEnd();
00736   }
00737   else 
00738   {
00739     glBegin(GL_TRIANGLES);
00740     for ( MeshCore::MeshFacetArray::_TConstIterator it = rFacets->begin(); it != rFacets->end(); ++it )
00741     {
00742       glVertex((*rPoints)[it->_aulPoints[0]]);
00743       glVertex((*rPoints)[it->_aulPoints[1]]);
00744       glVertex((*rPoints)[it->_aulPoints[2]]);
00745     }
00746     glEnd();
00747   }
00748 }
00749 
00753 void SoFCMeshFaceSet::drawPoints(const MeshCore::MeshPointArray * rPoints, 
00754                                  const MeshCore::MeshFacetArray* rFacets, SbBool needNormals, SbBool ccw) const
00755 {
00756   int mod = rFacets->size()/MaximumTriangles+1;
00757 
00758   float size = std::min<float>((float)mod,3.0f);
00759   glPointSize(size);
00760 
00761   if (needNormals)
00762   {
00763     glBegin(GL_POINTS);
00764     int ct=0;
00765     if ( ccw ) {
00766       for ( MeshCore::MeshFacetArray::_TConstIterator it = rFacets->begin(); it != rFacets->end(); ++it, ct++ )
00767       {
00768         if ( ct%mod==0 ) {
00769           const MeshCore::MeshPoint& v0 = (*rPoints)[it->_aulPoints[0]];
00770           const MeshCore::MeshPoint& v1 = (*rPoints)[it->_aulPoints[1]];
00771           const MeshCore::MeshPoint& v2 = (*rPoints)[it->_aulPoints[2]];
00772 
00773           // Calculate the normal n = (v1-v0)x(v2-v0)
00774           float n[3];
00775           n[0] = (v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y);
00776           n[1] = (v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z);
00777           n[2] = (v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x);
00778       
00779           // Calculate the center point p=(v0+v1+v2)/3
00780           float p[3];
00781           p[0] = (v0.x+v1.x+v2.x)/3.0f;
00782           p[1] = (v0.y+v1.y+v2.y)/3.0f;
00783           p[2] = (v0.z+v1.z+v2.z)/3.0f;
00784           glNormal3fv(n);
00785           glVertex3fv(p);
00786         }
00787       }
00788     } else {
00789       for ( MeshCore::MeshFacetArray::_TConstIterator it = rFacets->begin(); it != rFacets->end(); ++it, ct++ )
00790       {
00791         if ( ct%mod==0 ) {
00792           const MeshCore::MeshPoint& v0 = (*rPoints)[it->_aulPoints[0]];
00793           const MeshCore::MeshPoint& v1 = (*rPoints)[it->_aulPoints[1]];
00794           const MeshCore::MeshPoint& v2 = (*rPoints)[it->_aulPoints[2]];
00795 
00796           // Calculate the normal n = -(v1-v0)x(v2-v0)
00797           float n[3];
00798           n[0] = -((v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y));
00799           n[1] = -((v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z));
00800           n[2] = -((v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x));
00801       
00802           // Calculate the center point p=(v0+v1+v2)/3
00803           float p[3];
00804           p[0] = (v0.x+v1.x+v2.x)/3.0f;
00805           p[1] = (v0.y+v1.y+v2.y)/3.0f;
00806           p[2] = (v0.z+v1.z+v2.z)/3.0f;
00807           glNormal3fv(n);
00808           glVertex3fv(p);
00809         }
00810       }
00811     }
00812     glEnd();
00813   }
00814   else 
00815   {
00816     glBegin(GL_POINTS);
00817     int ct=0;
00818     for ( MeshCore::MeshFacetArray::_TConstIterator it = rFacets->begin(); it != rFacets->end(); ++it, ct++ )
00819     {
00820       if (ct%mod==0) {
00821         const MeshCore::MeshPoint& v0 = (*rPoints)[it->_aulPoints[0]];
00822         const MeshCore::MeshPoint& v1 = (*rPoints)[it->_aulPoints[1]];
00823         const MeshCore::MeshPoint& v2 = (*rPoints)[it->_aulPoints[2]];
00824         // Calculate the center point p=(v0+v1+v2)/3
00825         float p[3];
00826         p[0] = (v0.x+v1.x+v2.x)/3.0f;
00827         p[1] = (v0.y+v1.y+v2.y)/3.0f;
00828         p[2] = (v0.z+v1.z+v2.z)/3.0f;
00829         glVertex3fv(p);
00830       }
00831     }
00832     glEnd();
00833   }
00834 }
00835 
00836 // test bbox intersection
00837 //static SbBool
00838 //SoFCMeshFaceSet_ray_intersect(SoRayPickAction * action, const SbBox3f & box)
00839 //{
00840 //    if (box.isEmpty()) return FALSE;
00841 //    return action->intersect(box, TRUE);
00842 //}
00843 
00847 void
00848 SoFCMeshFaceSet::rayPick(SoRayPickAction * action)
00849 {
00850     //if (this->shouldRayPick(action)) {
00851     //    this->computeObjectSpaceRay(action);
00852 
00853     //    const SoBoundingBoxCache* bboxcache = getBoundingBoxCache();
00854     //    if (!bboxcache || !bboxcache->isValid(action->getState()) ||
00855     //        SoFCMeshFaceSet_ray_intersect(action, bboxcache->getProjectedBox())) {
00856     //        this->generatePrimitives(action);
00857     //    }
00858     //}
00859     inherited::rayPick(action);
00860 }
00861 
00867 void SoFCMeshFaceSet::generatePrimitives(SoAction* action)
00868 {
00869   SoState*  state = action->getState();
00870   const MeshCore::MeshPointArray * rPoints = SoFCMeshVertexElement::get(state);
00871   const MeshCore::MeshFacetArray * rFacets = SoFCMeshFacetElement::get(state);
00872   if ( !rPoints || rPoints->size() < 3 )
00873     return;
00874   if ( !rFacets || rPoints->size() < 1 )
00875     return;
00876 
00877 #if 0
00878   // In case we have too many triangles we just create a rough model of the original mesh
00879   if ( this->MaximumTriangles < rFacets->size() ) {
00880     // We notify this shape when the data has changed because just counting the number of triangles won't always work.
00881     // 
00882     if ( meshChanged ) {
00883       try {
00884         createProxyModel(rPoints, rFacets, FALSE);
00885         meshChanged = false;
00886       } catch (const Base::MemoryException&) {
00887           Base::Console().Log("Not enough memory to create a proxy model, use its bounding box instead\n");
00888           try {
00889             // try to create a triangulation of the bbox instead
00890             createProxyModel(rPoints, rFacets, TRUE);
00891             meshChanged = false;
00892           } catch (const Base::MemoryException&) {
00893               Base::Console().Log("Not enough memory to make the object pickable\n");
00894               return;
00895           }
00896       }
00897     }
00898     SoPrimitiveVertex vertex;
00899     beginShape(action, TRIANGLES, 0);
00900     try 
00901     {
00902         int i=0;
00903         while ( i<coordIndex.getNum() )
00904         {
00905           const SbVec3f& v0 = point[coordIndex[i++]]; 
00906           const SbVec3f& v1 = point[coordIndex[i++]]; 
00907           const SbVec3f& v2 = point[coordIndex[i++]]; 
00908 
00909           // Calculate the normal n = (v1-v0)x(v2-v0)
00910           SbVec3f n;
00911           n[0] = (v1[1]-v0[1])*(v2[2]-v0[2])-(v1[2]-v0[2])*(v2[1]-v0[1]);
00912           n[1] = (v1[2]-v0[2])*(v2[0]-v0[0])-(v1[0]-v0[0])*(v2[2]-v0[2]);
00913           n[2] = (v1[0]-v0[0])*(v2[1]-v0[1])-(v1[1]-v0[1])*(v2[0]-v0[0]);
00914 
00915           // Set the normal
00916           vertex.setNormal(n);
00917 
00918           vertex.setPoint( v0 );
00919           shapeVertex(&vertex);
00920           vertex.setPoint( v1 );
00921           shapeVertex(&vertex);
00922           vertex.setPoint( v2 );
00923           shapeVertex(&vertex);
00924         }
00925     } catch (const Base::MemoryException&) {
00926         Base::Console().Log("Not enough memory to generate primitives from the proxy model\n");
00927     }
00928     endShape();
00929   } else {
00930 #endif
00931     // get material binding
00932     Binding mbind = this->findMaterialBinding(state);
00933 
00934     // Create the information when moving over or picking into the scene
00935     SoPrimitiveVertex vertex;
00936     SoPointDetail pointDetail;
00937     SoFaceDetail faceDetail;
00938 
00939     vertex.setDetail(&pointDetail);
00940 
00941     beginShape(action, TRIANGLES, &faceDetail);
00942     try 
00943     {
00944         for ( MeshCore::MeshFacetArray::_TConstIterator it = rFacets->begin(); it != rFacets->end(); ++it )
00945         {
00946           const MeshCore::MeshPoint& v0 = (*rPoints)[it->_aulPoints[0]];
00947           const MeshCore::MeshPoint& v1 = (*rPoints)[it->_aulPoints[1]];
00948           const MeshCore::MeshPoint& v2 = (*rPoints)[it->_aulPoints[2]];
00949 
00950           // Calculate the normal n = (v1-v0)x(v2-v0)
00951           SbVec3f n;
00952           n[0] = (v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y);
00953           n[1] = (v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z);
00954           n[2] = (v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x);
00955 
00956           // Set the normal
00957           vertex.setNormal(n);
00958 
00959           // Vertex 0
00960           if (mbind == PER_VERTEX_INDEXED || mbind == PER_FACE_INDEXED) {
00961             pointDetail.setMaterialIndex(it->_aulPoints[0]);
00962             vertex.setMaterialIndex(it->_aulPoints[0]);
00963           }
00964           pointDetail.setCoordinateIndex(it->_aulPoints[0]);
00965           vertex.setPoint(sbvec3f(v0));
00966           shapeVertex(&vertex);
00967 
00968           // Vertex 1
00969           if (mbind == PER_VERTEX_INDEXED || mbind == PER_FACE_INDEXED) {
00970             pointDetail.setMaterialIndex(it->_aulPoints[1]);
00971             vertex.setMaterialIndex(it->_aulPoints[1]);
00972           }
00973           pointDetail.setCoordinateIndex(it->_aulPoints[1]);
00974           vertex.setPoint(sbvec3f(v1));
00975           shapeVertex(&vertex);
00976 
00977           // Vertex 2
00978           if (mbind == PER_VERTEX_INDEXED || mbind == PER_FACE_INDEXED) {
00979             pointDetail.setMaterialIndex(it->_aulPoints[2]);
00980             vertex.setMaterialIndex(it->_aulPoints[2]);
00981           }
00982           pointDetail.setCoordinateIndex(it->_aulPoints[2]);
00983           vertex.setPoint(sbvec3f(v2));
00984           shapeVertex(&vertex);
00985 
00986           // Increment for the next face
00987           faceDetail.incFaceIndex();
00988         }
00989     } catch (const Base::MemoryException&) {
00990         Base::Console().Log("Not enough memory to generate primitives\n");
00991     }
00992 
00993     endShape();
00994 #if 0
00995   }
00996 #endif
00997 }
00998 
01004 SoDetail * SoFCMeshFaceSet::createTriangleDetail(SoRayPickAction * action,
01005                                               const SoPrimitiveVertex * v1,
01006                                               const SoPrimitiveVertex * v2,
01007                                               const SoPrimitiveVertex * v3,
01008                                               SoPickedPoint * pp)
01009 {
01010 #if 0
01011   if ( this->MaximumTriangles < countTriangles(action) ) {
01012     return 0;
01013   } else {
01014 #endif
01015     SoDetail* detail = inherited::createTriangleDetail(action, v1, v2, v3, pp);
01016     return detail;
01017 #if 0
01018   }
01019 #endif
01020 }
01021 
01025 void SoFCMeshFaceSet::computeBBox(SoAction *action, SbBox3f &box, SbVec3f &center)
01026 {
01027   SoState*  state = action->getState();
01028   const MeshCore::MeshPointArray * rPoints = SoFCMeshVertexElement::get(state);
01029   if (rPoints && rPoints->size() > 0) {
01030     Base::BoundBox3f cBox;
01031     for ( MeshCore::MeshPointArray::_TConstIterator it = rPoints->begin(); it != rPoints->end(); ++it )
01032       cBox &= (*it);
01033     box.setBounds(SbVec3f(cBox.MinX,cBox.MinY,cBox.MinZ),
01034                               SbVec3f(cBox.MaxX,cBox.MaxY,cBox.MaxZ));
01035     Base::Vector3f mid = cBox.CalcCenter();
01036     center.setValue(mid.x,mid.y,mid.z);
01037   }
01038   else {
01039     box.setBounds(SbVec3f(0,0,0), SbVec3f(0,0,0));
01040     center.setValue(0.0f,0.0f,0.0f);
01041   }
01042 }
01043 
01047 void SoFCMeshFaceSet::getPrimitiveCount(SoGetPrimitiveCountAction * action)
01048 {
01049   if (!this->shouldPrimitiveCount(action)) return;
01050   SoState*  state = action->getState();
01051   const MeshCore::MeshFacetArray * coordIndex = SoFCMeshFacetElement::get(state);
01052   action->addNumTriangles(coordIndex->size());
01053 }
01054 
01058 unsigned int SoFCMeshFaceSet::countTriangles(SoAction * action) const
01059 {
01060   SoState*  state = action->getState();
01061   const MeshCore::MeshFacetArray * coordIndex = SoFCMeshFacetElement::get(state);
01062   return coordIndex->size();
01063 }
01064 
01065 // -------------------------------------------------------
01066 
01067 SO_NODE_SOURCE(SoFCMeshOpenEdgeSet);
01068 
01069 void SoFCMeshOpenEdgeSet::initClass()
01070 {
01071   SO_NODE_INIT_CLASS(SoFCMeshOpenEdgeSet, SoShape, "Shape");
01072 }
01073 
01074 SoFCMeshOpenEdgeSet::SoFCMeshOpenEdgeSet()
01075 {
01076   SO_NODE_CONSTRUCTOR(SoFCMeshOpenEdgeSet);
01077 }
01078 
01082 void SoFCMeshOpenEdgeSet::GLRender(SoGLRenderAction *action)
01083 {
01084   if (shouldGLRender(action))
01085   {
01086     SoState*  state = action->getState();
01087     const MeshCore::MeshPointArray * coords = SoFCMeshVertexElement::get(state);
01088     const MeshCore::MeshFacetArray * index = SoFCMeshFacetElement::get(state);
01089 
01090     SoMaterialBundle mb(action);
01091     SoTextureCoordinateBundle tb(action, TRUE, FALSE);
01092     SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);
01093     mb.sendFirst();  // make sure we have the correct material
01094 
01095     drawLines(coords,index);
01096 
01097     // Disable caching for this node
01098     SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE);
01099   }
01100 }
01101 
01105 void SoFCMeshOpenEdgeSet::drawLines(const MeshCore::MeshPointArray * rPoints, 
01106                                     const MeshCore::MeshFacetArray* rFacets) const
01107 {
01108   // When rendering open edges use the given line width * 3 
01109   GLfloat lineWidth;
01110   glGetFloatv(GL_LINE_WIDTH, &lineWidth);
01111   glLineWidth(3.0f*lineWidth);
01112 
01113   // Use the data structure directly and not through MeshFacetIterator as this
01114   // class is quite slowly (at least for rendering)
01115   glBegin(GL_LINES);
01116   for ( MeshCore::MeshFacetArray::_TConstIterator it = rFacets->begin(); it != rFacets->end(); ++it ) {
01117     for ( int i=0; i<3; i++ ) {
01118       if ( it->_aulNeighbours[i] == ULONG_MAX ) {
01119         glVertex((*rPoints)[it->_aulPoints[i]]);
01120         glVertex((*rPoints)[it->_aulPoints[(i+1)%3]]);
01121       }
01122     }
01123   }
01124 
01125   glEnd();
01126 }
01127 
01128 void SoFCMeshOpenEdgeSet::generatePrimitives(SoAction* action)
01129 {
01130   // do not create primitive information as an SoFCMeshFaceSet should already be used that delivers the information
01131   SoState*  state = action->getState();
01132   const MeshCore::MeshPointArray * rPoints = SoFCMeshVertexElement::get(state);
01133   const MeshCore::MeshFacetArray * rFacets = SoFCMeshFacetElement::get(state);
01134 
01135   // Create the information when moving over or picking into the scene
01136   SoPrimitiveVertex vertex;
01137   SoPointDetail pointDetail;
01138   SoLineDetail lineDetail;
01139 
01140   vertex.setDetail(&pointDetail);
01141 
01142   beginShape(action, LINES, &lineDetail);
01143   for ( MeshCore::MeshFacetArray::_TConstIterator it = rFacets->begin(); it != rFacets->end(); ++it )
01144   {
01145     for ( int i=0; i<3; i++ ) {
01146       if ( it->_aulNeighbours[i] == ULONG_MAX ) {
01147         const MeshCore::MeshPoint& v0 = (*rPoints)[it->_aulPoints[i]];
01148         const MeshCore::MeshPoint& v1 = (*rPoints)[it->_aulPoints[(i+1)%3]];
01149 
01150         // Vertex 0
01151         pointDetail.setCoordinateIndex(it->_aulPoints[i]);
01152         vertex.setPoint(sbvec3f(v0));
01153         shapeVertex(&vertex);
01154 
01155         // Vertex 1
01156         pointDetail.setCoordinateIndex(it->_aulPoints[(i+1)%3]);
01157         vertex.setPoint(sbvec3f(v1));
01158         shapeVertex(&vertex);
01159 
01160         // Increment for the next open edge
01161         lineDetail.incLineIndex();
01162       }
01163     }
01164   }
01165 
01166   endShape();
01167 }
01168 
01172 void SoFCMeshOpenEdgeSet::computeBBox(SoAction *action, SbBox3f &box, SbVec3f &center)
01173 {
01174   SoState*  state = action->getState();
01175   const MeshCore::MeshPointArray * rPoints = SoFCMeshVertexElement::get(state);
01176   if (rPoints && rPoints->size() > 0) {
01177     Base::BoundBox3f cBox;
01178     for ( MeshCore::MeshPointArray::_TConstIterator it = rPoints->begin(); it != rPoints->end(); ++it )
01179       cBox &= (*it);
01180     box.setBounds(SbVec3f(cBox.MinX,cBox.MinY,cBox.MinZ),
01181                               SbVec3f(cBox.MaxX,cBox.MaxY,cBox.MaxZ));
01182     Base::Vector3f mid = cBox.CalcCenter();
01183     center.setValue(mid.x,mid.y,mid.z);
01184   }
01185   else {
01186     box.setBounds(SbVec3f(0,0,0), SbVec3f(0,0,0));
01187     center.setValue(0.0f,0.0f,0.0f);
01188   }
01189 }
01190 
01194 void SoFCMeshOpenEdgeSet::getPrimitiveCount(SoGetPrimitiveCountAction * action)
01195 {
01196   if (!this->shouldPrimitiveCount(action)) return;
01197   SoState*  state = action->getState();
01198   const MeshCore::MeshFacetArray * rFaces = SoFCMeshFacetElement::get(state);
01199   
01200   // Count number of open edges first
01201   int ctEdges=0;
01202   for ( MeshCore::MeshFacetArray::_TConstIterator jt = rFaces->begin(); jt != rFaces->end(); ++jt ) {
01203     for ( int i=0; i<3; i++ ) {
01204       if ( jt->_aulNeighbours[i] == ULONG_MAX ) {
01205         ctEdges++;
01206       }
01207     }
01208   }
01209 
01210   action->addNumLines(ctEdges);
01211 }

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