00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00074
00075 SO_SFIELD_SOURCE(SoSFMeshFacetArray, MeshCore::MeshFacetArray*, MeshCore::MeshFacetArray*);
00076
00077
00078 void SoSFMeshFacetArray::initClass()
00079 {
00080
00081
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
00091
00092 SbBool SoSFMeshFacetArray::readValue(SoInput *in)
00093 {
00094
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
00104 if (in->isBinary()) {
00105 int numtoread;
00106 READ_VAL(numtoread);
00107
00108
00109
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
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
00130 }
00131 else {
00132 in->putBack(c);
00133
00134 while (TRUE) {
00135
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); }
00142
00143
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
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
00168 MeshCore::MeshPointArray vertex;
00169 MeshCore::MeshKernel mesh;
00170
00171 mesh.Adopt(vertex, *value, true);
00172
00173 mesh.Adopt(vertex, *value, false);
00174
00175
00176
00177
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
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
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 * ) 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
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
00341 void SoFCMeshFacet::doAction(SoAction * action)
00342 {
00343 SoFCMeshFacetElement::set(action->getState(), this, coordIndex.getValue());
00344 }
00345
00346
00347 void SoFCMeshFacet::GLRender(SoGLRenderAction * action)
00348 {
00349 SoFCMeshFacet::doAction(action);
00350 }
00351
00352
00353 void SoFCMeshFacet::callback(SoCallbackAction * action)
00354 {
00355 SoFCMeshFacet::doAction(action);
00356 }
00357
00358
00359 void SoFCMeshFacet::pick(SoPickAction * action)
00360 {
00361 SoFCMeshFacet::doAction(action);
00362 }
00363
00364
00365 void SoFCMeshFacet::getBoundingBox(SoGetBoundingBoxAction * action)
00366 {
00367 SoFCMeshFacet::doAction(action);
00368 }
00369
00370
00371 void SoFCMeshFacet::getPrimitiveCount(SoGetPrimitiveCountAction * action)
00372 {
00373 SoFCMeshFacet::doAction(action);
00374 }
00375
00376
00377
00395
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
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
00412 inline void glNormal(float* n)
00413 {
00414 glNormal3fv(n);
00415 }
00416
00417
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
00483 MeshCore::MeshKernel mesh;
00484 mesh.Assign(*rPoints, *rFaces,false);
00485
00486
00487 float fAvgLen = 5.0f * MeshCore::MeshAlgorithm(mesh).GetAverageEdgeLength();
00488
00489
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
00620
00621 SbBool needNormals = !mb.isColorOnly();
00622 mb.sendFirst();
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
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
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
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
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
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
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
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
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
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
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
00837
00838
00839
00840
00841
00842
00843
00847 void
00848 SoFCMeshFaceSet::rayPick(SoRayPickAction * action)
00849 {
00850
00851
00852
00853
00854
00855
00856
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
00879 if ( this->MaximumTriangles < rFacets->size() ) {
00880
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
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
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
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
00932 Binding mbind = this->findMaterialBinding(state);
00933
00934
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
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
00957 vertex.setNormal(n);
00958
00959
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
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
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
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 ¢er)
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();
01094
01095 drawLines(coords,index);
01096
01097
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
01109 GLfloat lineWidth;
01110 glGetFloatv(GL_LINE_WIDTH, &lineWidth);
01111 glLineWidth(3.0f*lineWidth);
01112
01113
01114
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
01131 SoState* state = action->getState();
01132 const MeshCore::MeshPointArray * rPoints = SoFCMeshVertexElement::get(state);
01133 const MeshCore::MeshFacetArray * rFacets = SoFCMeshFacetElement::get(state);
01134
01135
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
01151 pointDetail.setCoordinateIndex(it->_aulPoints[i]);
01152 vertex.setPoint(sbvec3f(v0));
01153 shapeVertex(&vertex);
01154
01155
01156 pointDetail.setCoordinateIndex(it->_aulPoints[(i+1)%3]);
01157 vertex.setPoint(sbvec3f(v1));
01158 shapeVertex(&vertex);
01159
01160
01161 lineDetail.incLineIndex();
01162 }
01163 }
01164 }
01165
01166 endShape();
01167 }
01168
01172 void SoFCMeshOpenEdgeSet::computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er)
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
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 }