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 # include <algorithm>
00028 # ifdef FC_OS_WIN32
00029 # include <windows.h>
00030 # endif
00031 # ifdef FC_OS_MACOSX
00032 # include <OpenGL/gl.h>
00033 # include <OpenGL/glu.h>
00034 # else
00035 # include <GL/gl.h>
00036 # include <GL/glu.h>
00037 # endif
00038 # include <Inventor/actions/SoCallbackAction.h>
00039 # include <Inventor/actions/SoGetBoundingBoxAction.h>
00040 # include <Inventor/actions/SoGetPrimitiveCountAction.h>
00041 # include <Inventor/actions/SoGLRenderAction.h>
00042 # include <Inventor/actions/SoPickAction.h>
00043 # include <Inventor/actions/SoWriteAction.h>
00044 # include <Inventor/details/SoFaceDetail.h>
00045 # include <Inventor/errors/SoReadError.h>
00046 # include <Inventor/misc/SoState.h>
00047 #endif
00048
00049 #include "SoFCMeshObject.h"
00050 #include <Base/Console.h>
00051 #include <Base/Exception.h>
00052 #include <Gui/SoFCInteractiveElement.h>
00053 #include <Gui/SoFCSelectionAction.h>
00054 #include <Mod/Mesh/App/Core/Algorithm.h>
00055 #include <Mod/Mesh/App/Core/MeshIO.h>
00056 #include <Mod/Mesh/App/Core/MeshKernel.h>
00057 #include <Mod/Mesh/App/Core/Elements.h>
00058 #include <Mod/Mesh/App/Core/Grid.h>
00059
00060 using namespace MeshGui;
00061
00062
00063 class SoOutputStreambuf : public std::streambuf
00064 {
00065 public:
00066 SoOutputStreambuf(SoOutput* o) : out(o)
00067 {
00068 }
00069 protected:
00070 int overflow(int c = EOF)
00071 {
00072 if (c != EOF) {
00073 char z = static_cast<char>(c);
00074 out->write(z);
00075 }
00076 return c;
00077 }
00078 std::streamsize xsputn (const char* s, std::streamsize num)
00079 {
00080 out->write(s);
00081 return num;
00082 }
00083
00084 private:
00085 SoOutput* out;
00086 };
00087
00088 class SoOutputStream : public std::ostream
00089 {
00090 public:
00091 SoOutputStream(SoOutput* o) : std::ostream(0), buf(o)
00092 {
00093 this->rdbuf(&buf);
00094 }
00095 private:
00096 SoOutputStreambuf buf;
00097 };
00098
00099 class SoInputStreambuf : public std::streambuf
00100 {
00101 public:
00102 SoInputStreambuf(SoInput* o) : inp(o)
00103 {
00104 setg (buffer+pbSize,
00105 buffer+pbSize,
00106 buffer+pbSize);
00107 }
00108 protected:
00109 int underflow()
00110 {
00111 if (gptr() < egptr()) {
00112 return *gptr();
00113 }
00114
00115 int numPutback;
00116 numPutback = gptr() - eback();
00117 if (numPutback > pbSize) {
00118 numPutback = pbSize;
00119 }
00120
00121 memcpy (buffer+(pbSize-numPutback), gptr()-numPutback, numPutback);
00122
00123 int num=0;
00124 for (int i=0; i<bufSize; i++) {
00125 char c;
00126 SbBool ok = inp->get(c);
00127 if (ok) {
00128 num++;
00129 buffer[pbSize+i] = c;
00130 if (c == '\n')
00131 break;
00132 }
00133 else if (num==0) {
00134 return EOF;
00135 }
00136 }
00137
00138 setg (buffer+(pbSize-numPutback),
00139 buffer+pbSize,
00140 buffer+pbSize+num);
00141
00142 return *gptr();
00143 }
00144
00145 private:
00146 static const int pbSize = 4;
00147 static const int bufSize = 1024;
00148 char buffer[bufSize+pbSize];
00149 SoInput* inp;
00150 };
00151
00152 class SoInputStream : public std::istream
00153 {
00154 public:
00155 SoInputStream(SoInput* o) : std::istream(0), buf(o)
00156 {
00157 this->rdbuf(&buf);
00158 }
00159 ~SoInputStream()
00160 {
00161 }
00162
00163 private:
00164 SoInputStreambuf buf;
00165 };
00166
00167
00168
00169 SO_SFIELD_SOURCE(SoSFMeshObject, const Mesh::MeshObject*, const Mesh::MeshObject*);
00170
00171
00172 void SoSFMeshObject::initClass()
00173 {
00174
00175
00176 SO_SFIELD_INIT_CLASS(SoSFMeshObject, SoSField);
00177 }
00178
00179
00180
00181 SbBool SoSFMeshObject::readValue(SoInput *in)
00182 {
00183 if (!in->isBinary()) {
00184 SoInputStream str(in);
00185 MeshCore::MeshKernel kernel;
00186 MeshCore::MeshInput(kernel).LoadMeshNode(str);
00187 value = new Mesh::MeshObject(kernel);
00188
00189
00190
00191
00192 this->valueChanged();
00193
00194 return TRUE;
00195 }
00196
00197 int32_t countPt;
00198 in->read(countPt);
00199 std::vector<float> verts(countPt);
00200 in->readBinaryArray(&(verts[0]),countPt);
00201
00202 MeshCore::MeshPointArray rPoints;
00203 rPoints.reserve(countPt/3);
00204 for (std::vector<float>::iterator it = verts.begin();
00205 it != verts.end();) {
00206 Base::Vector3f p;
00207 p.x = *it; it++;
00208 p.y = *it; it++;
00209 p.z = *it; it++;
00210 rPoints.push_back(p);
00211 }
00212
00213 int32_t countFt;
00214 in->read(countFt);
00215 std::vector<int32_t> faces(countFt);
00216 in->readBinaryArray(&(faces[0]),countFt);
00217
00218 MeshCore::MeshFacetArray rFacets;
00219 rFacets.reserve(countFt/3);
00220 for (std::vector<int32_t>::iterator it = faces.begin();
00221 it != faces.end();) {
00222 MeshCore::MeshFacet f;
00223 f._aulPoints[0] = *it; it++;
00224 f._aulPoints[1] = *it; it++;
00225 f._aulPoints[2] = *it; it++;
00226 rFacets.push_back(f);
00227 }
00228
00229 MeshCore::MeshKernel kernel;
00230 kernel.Adopt(rPoints, rFacets, true);
00231 value = new Mesh::MeshObject(kernel);
00232
00233
00234
00235
00236 this->valueChanged();
00237
00238 return TRUE;
00239 }
00240
00241
00242 void SoSFMeshObject::writeValue(SoOutput *out) const
00243 {
00244 if (!out->isBinary()) {
00245 SoOutputStream str(out);
00246 MeshCore::MeshOutput(value->getKernel()).SaveMeshNode(str);
00247 return;
00248 }
00249
00250 if (!value) {
00251 int32_t count = 0;
00252 out->write(count);
00253 out->write(count);
00254 return;
00255 }
00256 const MeshCore::MeshPointArray& rPoints = value->getKernel().GetPoints();
00257 std::vector<float> verts;
00258 verts.reserve(3*rPoints.size());
00259 for (MeshCore::MeshPointArray::_TConstIterator it = rPoints.begin();
00260 it != rPoints.end(); ++it) {
00261 verts.push_back(it->x);
00262 verts.push_back(it->y);
00263 verts.push_back(it->z);
00264 }
00265
00266 int32_t countPt = (int32_t)verts.size();
00267 out->write(countPt);
00268 out->writeBinaryArray(&(verts[0]),countPt);
00269
00270 const MeshCore::MeshFacetArray& rFacets = value->getKernel().GetFacets();
00271 std::vector<uint32_t> faces;
00272 faces.reserve(3*rFacets.size());
00273 for (MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin();
00274 it != rFacets.end(); ++it) {
00275 faces.push_back((int32_t)it->_aulPoints[0]);
00276 faces.push_back((int32_t)it->_aulPoints[1]);
00277 faces.push_back((int32_t)it->_aulPoints[2]);
00278 }
00279
00280 int32_t countFt = (int32_t)faces.size();
00281 out->write(countFt);
00282 out->writeBinaryArray((const int32_t*)&(faces[0]),countFt);
00283 }
00284
00285
00286
00287 SO_ELEMENT_SOURCE(SoFCMeshObjectElement);
00288
00289 void SoFCMeshObjectElement::initClass()
00290 {
00291 SO_ELEMENT_INIT_CLASS(SoFCMeshObjectElement, inherited);
00292 }
00293
00294 void SoFCMeshObjectElement::init(SoState * state)
00295 {
00296 inherited::init(state);
00297 this->mesh = 0;
00298 }
00299
00300 SoFCMeshObjectElement::~SoFCMeshObjectElement()
00301 {
00302 }
00303
00304 void SoFCMeshObjectElement::set(SoState * const state, SoNode * const node, const Mesh::MeshObject * const mesh)
00305 {
00306 SoFCMeshObjectElement * elem = (SoFCMeshObjectElement *)
00307 SoReplacedElement::getElement(state, classStackIndex, node);
00308 if (elem) {
00309 elem->mesh = mesh;
00310 elem->nodeId = node->getNodeId();
00311 }
00312 }
00313
00314 const Mesh::MeshObject * SoFCMeshObjectElement::get(SoState * const state)
00315 {
00316 return SoFCMeshObjectElement::getInstance(state)->mesh;
00317 }
00318
00319 const SoFCMeshObjectElement * SoFCMeshObjectElement::getInstance(SoState * state)
00320 {
00321 return (const SoFCMeshObjectElement *) SoElement::getConstElement(state, classStackIndex);
00322 }
00323
00324 void SoFCMeshObjectElement::print(FILE * ) const
00325 {
00326 }
00327
00328
00329
00330 SO_NODE_SOURCE(SoFCMeshPickNode);
00331
00335 SoFCMeshPickNode::SoFCMeshPickNode(void) : meshGrid(0)
00336 {
00337 SO_NODE_CONSTRUCTOR(SoFCMeshPickNode);
00338
00339 SO_NODE_ADD_FIELD(mesh, (0));
00340 }
00341
00345 SoFCMeshPickNode::~SoFCMeshPickNode()
00346 {
00347 delete meshGrid;
00348 }
00349
00350
00351 void SoFCMeshPickNode::initClass(void)
00352 {
00353 SO_NODE_INIT_CLASS(SoFCMeshPickNode, SoNode, "Node");
00354 }
00355
00356 void SoFCMeshPickNode::notify(SoNotList *list)
00357 {
00358 SoField *f = list->getLastField();
00359 if (f == &mesh) {
00360 const Mesh::MeshObject* meshObject = mesh.getValue();
00361 if (meshObject) {
00362 MeshCore::MeshAlgorithm alg(meshObject->getKernel());
00363 float fAvgLen = alg.GetAverageEdgeLength();
00364 delete meshGrid;
00365 meshGrid = new MeshCore::MeshFacetGrid(meshObject->getKernel(), 5.0f * fAvgLen);
00366 }
00367 }
00368 }
00369
00370
00371 void SoFCMeshPickNode::rayPick(SoRayPickAction * action)
00372 {
00373 }
00374
00375
00376 void SoFCMeshPickNode::pick(SoPickAction * action)
00377 {
00378 SoRayPickAction* raypick = static_cast<SoRayPickAction*>(action);
00379 raypick->setObjectSpace();
00380
00381 const Mesh::MeshObject* meshObject = mesh.getValue();
00382 MeshCore::MeshAlgorithm alg(meshObject->getKernel());
00383
00384 const SbLine& line = raypick->getLine();
00385 const SbVec3f& pos = line.getPosition();
00386 const SbVec3f& dir = line.getDirection();
00387 Base::Vector3f pt(pos[0],pos[1],pos[2]);
00388 Base::Vector3f dr(dir[0],dir[1],dir[2]);
00389 unsigned long index;
00390 if (alg.NearestFacetOnRay(pt, dr, *meshGrid, pt, index)) {
00391 SoPickedPoint* pp = raypick->addIntersection(SbVec3f(pt.x,pt.y,pt.z));
00392 if (pp) {
00393 SoFaceDetail* det = new SoFaceDetail();
00394 det->setFaceIndex(index);
00395 pp->setDetail(det, this);
00396 }
00397 }
00398 }
00399
00400
00401
00402 SO_NODE_SOURCE(SoFCMeshGridNode);
00403
00407 SoFCMeshGridNode::SoFCMeshGridNode(void)
00408 {
00409 SO_NODE_CONSTRUCTOR(SoFCMeshGridNode);
00410
00411 SO_NODE_ADD_FIELD(minGrid, (SbVec3f(0,0,0)));
00412 SO_NODE_ADD_FIELD(maxGrid, (SbVec3f(0,0,0)));
00413 SO_NODE_ADD_FIELD(lenGrid, (SbVec3s(0,0,0)));
00414 }
00415
00419 SoFCMeshGridNode::~SoFCMeshGridNode()
00420 {
00421 }
00422
00423
00424 void SoFCMeshGridNode::initClass(void)
00425 {
00426 SO_NODE_INIT_CLASS(SoFCMeshGridNode, SoNode, "Node");
00427 }
00428
00429 void SoFCMeshGridNode::GLRender(SoGLRenderAction * action)
00430 {
00431 const SbVec3f& min = minGrid.getValue();
00432 const SbVec3f& max = maxGrid.getValue();
00433 const SbVec3s& len = lenGrid.getValue();
00434 short u,v,w; len.getValue(u,v,w);
00435 float minX, minY, minZ; min.getValue(minX, minY, minZ);
00436 float maxX, maxY, maxZ; max.getValue(maxX, maxY, maxZ);
00437 float dx = (maxX-minX)/(float)u;
00438 float dy = (maxY-minY)/(float)v;
00439 float dz = (maxZ-minZ)/(float)w;
00440 glColor3f(0.0f,1.0f,0.0);
00441 glBegin(GL_LINES);
00442 for (short i=0; i<u+1; i++) {
00443 for (short j=0; j<v+1; j++) {
00444 float p[3];
00445 p[0] = i * dx + minX;
00446 p[1] = j * dy + minY;
00447 p[2] = minZ;
00448 glVertex3fv(p);
00449
00450 p[0] = i * dx + minX;
00451 p[1] = j * dy + minY;
00452 p[2] = maxZ;
00453 glVertex3fv(p);
00454 }
00455 }
00456 for (short i=0; i<u+1; i++) {
00457 for (short j=0; j<w+1; j++) {
00458 float p[3];
00459 p[0] = i * dx + minX;
00460 p[1] = minY;
00461 p[2] = j * dz + minZ;
00462 glVertex3fv(p);
00463
00464 p[0] = i * dx + minX;
00465 p[1] = maxY;
00466 p[2] = j * dz + minZ;
00467 glVertex3fv(p);
00468 }
00469 }
00470 for (short i=0; i<v+1; i++) {
00471 for (short j=0; j<w+1; j++) {
00472 float p[3];
00473 p[0] = minX;
00474 p[1] = i * dy + minY;
00475 p[2] = j * dz + minZ;
00476 glVertex3fv(p);
00477
00478 p[0] = maxX;
00479 p[1] = i * dy + minY;
00480 p[2] = j * dz + minZ;
00481 glVertex3fv(p);
00482 }
00483 }
00484 glEnd();
00485 }
00486
00487
00488
00489 SO_NODE_SOURCE(SoFCMeshObjectNode);
00490
00494 SoFCMeshObjectNode::SoFCMeshObjectNode(void)
00495 {
00496 SO_NODE_CONSTRUCTOR(SoFCMeshObjectNode);
00497
00498 SO_NODE_ADD_FIELD(mesh, (0));
00499 }
00500
00504 SoFCMeshObjectNode::~SoFCMeshObjectNode()
00505 {
00506 }
00507
00508
00509 void SoFCMeshObjectNode::initClass(void)
00510 {
00511 SO_NODE_INIT_CLASS(SoFCMeshObjectNode, SoNode, "Node");
00512
00513 SO_ENABLE(SoGetBoundingBoxAction, SoFCMeshObjectElement);
00514 SO_ENABLE(SoGLRenderAction, SoFCMeshObjectElement);
00515 SO_ENABLE(SoPickAction, SoFCMeshObjectElement);
00516 SO_ENABLE(SoCallbackAction, SoFCMeshObjectElement);
00517 SO_ENABLE(SoGetPrimitiveCountAction, SoFCMeshObjectElement);
00518 }
00519
00520
00521 void SoFCMeshObjectNode::doAction(SoAction * action)
00522 {
00523 SoFCMeshObjectElement::set(action->getState(), this, mesh.getValue());
00524 }
00525
00526
00527 void SoFCMeshObjectNode::GLRender(SoGLRenderAction * action)
00528 {
00529 SoFCMeshObjectNode::doAction(action);
00530 }
00531
00532
00533 void SoFCMeshObjectNode::callback(SoCallbackAction * action)
00534 {
00535 SoFCMeshObjectNode::doAction(action);
00536 }
00537
00538
00539 void SoFCMeshObjectNode::pick(SoPickAction * action)
00540 {
00541 SoFCMeshObjectNode::doAction(action);
00542 }
00543
00544
00545 void SoFCMeshObjectNode::getBoundingBox(SoGetBoundingBoxAction * action)
00546 {
00547 SoFCMeshObjectNode::doAction(action);
00548 }
00549
00550
00551 void SoFCMeshObjectNode::getPrimitiveCount(SoGetPrimitiveCountAction * action)
00552 {
00553 SoFCMeshObjectNode::doAction(action);
00554 }
00555
00556
00557 inline void glVertex(const MeshCore::MeshPoint& _v)
00558 {
00559 float v[3];
00560 v[0]=_v.x; v[1]=_v.y;v[2]=_v.z;
00561 glVertex3fv(v);
00562 }
00563
00564
00565 inline void glNormal(const Base::Vector3f& _n)
00566 {
00567 float n[3];
00568 n[0]=_n.x; n[1]=_n.y;n[2]=_n.z;
00569 glNormal3fv(n);
00570 }
00571
00572
00573 inline void glNormal(float* n)
00574 {
00575 glNormal3fv(n);
00576 }
00577
00578
00579 inline SbVec3f sbvec3f(const Base::Vector3f& _v)
00580 {
00581 return SbVec3f(_v.x, _v.y, _v.z);
00582 }
00583
00584 SO_NODE_SOURCE(SoFCMeshObjectShape);
00585
00586 void SoFCMeshObjectShape::initClass()
00587 {
00588 SO_NODE_INIT_CLASS(SoFCMeshObjectShape, SoShape, "Shape");
00589 }
00590
00591 SoFCMeshObjectShape::SoFCMeshObjectShape() : renderTriangleLimit(100000), meshChanged(true)
00592 {
00593 SO_NODE_CONSTRUCTOR(SoFCMeshObjectShape);
00594 setName(SoFCMeshObjectShape::getClassTypeId().getName());
00595 }
00596
00597 void SoFCMeshObjectShape::notify(SoNotList * node)
00598 {
00599 inherited::notify(node);
00600 meshChanged = true;
00601 }
00602
00606 void SoFCMeshObjectShape::GLRender(SoGLRenderAction *action)
00607 {
00608 if (shouldGLRender(action))
00609 {
00610 SoState* state = action->getState();
00611
00612
00613
00614 glGetFloatv(GL_MODELVIEW_MATRIX, this->modelview);
00615 glGetFloatv(GL_PROJECTION_MATRIX, this->projection);
00616
00617 SbBool mode = Gui::SoFCInteractiveElement::get(state);
00618 const Mesh::MeshObject * mesh = SoFCMeshObjectElement::get(state);
00619 if (!mesh || mesh->countPoints() == 0) return;
00620
00621 Binding mbind = this->findMaterialBinding(state);
00622
00623 SoMaterialBundle mb(action);
00624
00625
00626 SbBool needNormals = !mb.isColorOnly();
00627 mb.sendFirst();
00628
00629 SbBool ccw = TRUE;
00630 if (SoShapeHintsElement::getVertexOrdering(state) == SoShapeHintsElement::CLOCKWISE)
00631 ccw = FALSE;
00632
00633 if (mode == false || mesh->countFacets() <= this->renderTriangleLimit) {
00634 if (mbind != OVERALL)
00635 drawFaces(mesh, &mb, mbind, needNormals, ccw);
00636 else
00637 drawFaces(mesh, 0, mbind, needNormals, ccw);
00638 }
00639 else {
00640 drawPoints(mesh, needNormals, ccw);
00641 }
00642
00643
00644
00645 }
00646 }
00647
00651 SoFCMeshObjectShape::Binding SoFCMeshObjectShape::findMaterialBinding(SoState * const state) const
00652 {
00653 Binding binding = OVERALL;
00654 SoMaterialBindingElement::Binding matbind = SoMaterialBindingElement::get(state);
00655
00656 switch (matbind) {
00657 case SoMaterialBindingElement::OVERALL:
00658 binding = OVERALL;
00659 break;
00660 case SoMaterialBindingElement::PER_VERTEX:
00661 binding = PER_VERTEX_INDEXED;
00662 break;
00663 case SoMaterialBindingElement::PER_VERTEX_INDEXED:
00664 binding = PER_VERTEX_INDEXED;
00665 break;
00666 case SoMaterialBindingElement::PER_PART:
00667 case SoMaterialBindingElement::PER_FACE:
00668 binding = PER_FACE_INDEXED;
00669 break;
00670 case SoMaterialBindingElement::PER_PART_INDEXED:
00671 case SoMaterialBindingElement::PER_FACE_INDEXED:
00672 binding = PER_FACE_INDEXED;
00673 break;
00674 default:
00675 break;
00676 }
00677 return binding;
00678 }
00679
00685 void SoFCMeshObjectShape::drawFaces(const Mesh::MeshObject * mesh, SoMaterialBundle* mb,
00686 Binding bind, SbBool needNormals, SbBool ccw) const
00687 {
00688 const MeshCore::MeshPointArray & rPoints = mesh->getKernel().GetPoints();
00689 const MeshCore::MeshFacetArray & rFacets = mesh->getKernel().GetFacets();
00690 bool perVertex = (mb && bind == PER_VERTEX_INDEXED);
00691 bool perFace = (mb && bind == PER_FACE_INDEXED);
00692
00693 if (needNormals)
00694 {
00695 glBegin(GL_TRIANGLES);
00696 if (ccw) {
00697
00698 for (MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it)
00699 {
00700 const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[0]];
00701 const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[1]];
00702 const MeshCore::MeshPoint& v2 = rPoints[it->_aulPoints[2]];
00703
00704
00705 float n[3];
00706 n[0] = (v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y);
00707 n[1] = (v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z);
00708 n[2] = (v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x);
00709
00710 if(perFace)
00711 mb->send(it-rFacets.begin(), TRUE);
00712 glNormal(n);
00713 if(perVertex)
00714 mb->send(it->_aulPoints[0], TRUE);
00715 glVertex(v0);
00716 if(perVertex)
00717 mb->send(it->_aulPoints[1], TRUE);
00718 glVertex(v1);
00719 if(perVertex)
00720 mb->send(it->_aulPoints[2], TRUE);
00721 glVertex(v2);
00722 }
00723 }
00724 else {
00725
00726 for (MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it)
00727 {
00728 const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[0]];
00729 const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[1]];
00730 const MeshCore::MeshPoint& v2 = rPoints[it->_aulPoints[2]];
00731
00732
00733 float n[3];
00734 n[0] = -((v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y));
00735 n[1] = -((v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z));
00736 n[2] = -((v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x));
00737
00738 glNormal(n);
00739 glVertex(v0);
00740 glVertex(v1);
00741 glVertex(v2);
00742 }
00743 }
00744 glEnd();
00745 }
00746 else {
00747 glBegin(GL_TRIANGLES);
00748 for (MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it)
00749 {
00750 glVertex(rPoints[it->_aulPoints[0]]);
00751 glVertex(rPoints[it->_aulPoints[1]]);
00752 glVertex(rPoints[it->_aulPoints[2]]);
00753 }
00754 glEnd();
00755 }
00756 }
00757
00761 void SoFCMeshObjectShape::drawPoints(const Mesh::MeshObject * mesh, SbBool needNormals, SbBool ccw) const
00762 {
00763 const MeshCore::MeshPointArray & rPoints = mesh->getKernel().GetPoints();
00764 const MeshCore::MeshFacetArray & rFacets = mesh->getKernel().GetFacets();
00765 int mod = rFacets.size()/renderTriangleLimit+1;
00766
00767 float size = std::min<float>((float)mod,3.0f);
00768 glPointSize(size);
00769
00770 if (needNormals)
00771 {
00772 glBegin(GL_POINTS);
00773 int ct=0;
00774 if (ccw) {
00775 for (MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it, ct++)
00776 {
00777 if (ct%mod==0) {
00778 const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[0]];
00779 const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[1]];
00780 const MeshCore::MeshPoint& v2 = rPoints[it->_aulPoints[2]];
00781
00782
00783 float n[3];
00784 n[0] = (v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y);
00785 n[1] = (v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z);
00786 n[2] = (v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x);
00787
00788
00789 float p[3];
00790 p[0] = (v0.x+v1.x+v2.x)/3.0f;
00791 p[1] = (v0.y+v1.y+v2.y)/3.0f;
00792 p[2] = (v0.z+v1.z+v2.z)/3.0f;
00793 glNormal3fv(n);
00794 glVertex3fv(p);
00795 }
00796 }
00797 }
00798 else {
00799 for (MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it, ct++)
00800 {
00801 if (ct%mod==0) {
00802 const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[0]];
00803 const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[1]];
00804 const MeshCore::MeshPoint& v2 = rPoints[it->_aulPoints[2]];
00805
00806
00807 float n[3];
00808 n[0] = -((v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y));
00809 n[1] = -((v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z));
00810 n[2] = -((v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x));
00811
00812
00813 float p[3];
00814 p[0] = (v0.x+v1.x+v2.x)/3.0f;
00815 p[1] = (v0.y+v1.y+v2.y)/3.0f;
00816 p[2] = (v0.z+v1.z+v2.z)/3.0f;
00817 glNormal3fv(n);
00818 glVertex3fv(p);
00819 }
00820 }
00821 }
00822 glEnd();
00823 }
00824 else {
00825 glBegin(GL_POINTS);
00826 int ct=0;
00827 for (MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it, ct++)
00828 {
00829 if (ct%mod==0) {
00830 const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[0]];
00831 const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[1]];
00832 const MeshCore::MeshPoint& v2 = rPoints[it->_aulPoints[2]];
00833
00834 float p[3];
00835 p[0] = (v0.x+v1.x+v2.x)/3.0f;
00836 p[1] = (v0.y+v1.y+v2.y)/3.0f;
00837 p[2] = (v0.z+v1.z+v2.z)/3.0f;
00838 glVertex3fv(p);
00839 }
00840 }
00841 glEnd();
00842 }
00843 }
00844
00845 void SoFCMeshObjectShape::doAction(SoAction * action)
00846 {
00847 if (action->getTypeId() == Gui::SoGLSelectAction::getClassTypeId()) {
00848 SoNode* node = action->getNodeAppliedTo();
00849 if (!node) return;
00850
00851
00852
00853 SoSearchAction sa;
00854 sa.setInterest(SoSearchAction::FIRST);
00855 sa.setSearchingAll(FALSE);
00856 sa.setType(SoFCMeshObjectNode::getClassTypeId(), 1);
00857 sa.apply(node);
00858 SoPath * path = sa.getPath();
00859 if (!path) return;
00860
00861
00862 SoNode* coords = path->getNodeFromTail(0);
00863 if (!(coords && coords->getTypeId().isDerivedFrom(SoFCMeshObjectNode::getClassTypeId())))
00864 return;
00865 const Mesh::MeshObject* mesh = static_cast<SoFCMeshObjectNode*>(coords)->mesh.getValue();
00866 startSelection(action, mesh);
00867 renderSelectionGeometry(mesh);
00868 stopSelection(action, mesh);
00869 }
00870
00871 inherited::doAction(action);
00872 }
00873
00874 void SoFCMeshObjectShape::startSelection(SoAction * action, const Mesh::MeshObject* mesh)
00875 {
00876 Gui::SoGLSelectAction *doaction = static_cast<Gui::SoGLSelectAction*>(action);
00877 const SbViewportRegion& vp = doaction->getViewportRegion();
00878 int x = vp.getViewportOriginPixels()[0];
00879 int y = vp.getViewportOriginPixels()[1];
00880 int w = vp.getViewportSizePixels()[0];
00881 int h = vp.getViewportSizePixels()[1];
00882
00883 unsigned int bufSize = 5*mesh->countFacets();
00884 this->selectBuf = new GLuint[bufSize];
00885
00886 glSelectBuffer(bufSize, selectBuf);
00887 glRenderMode(GL_SELECT);
00888
00889 glInitNames();
00890 glPushName(-1);
00891
00892
00893 GLint viewport[4];
00894 glGetIntegerv(GL_VIEWPORT,viewport);
00895 glMatrixMode(GL_PROJECTION);
00896
00897 glPushMatrix();
00898 glLoadIdentity();
00899 gluPickMatrix(x, y, w, h, viewport);
00900 glMultMatrixf(this->projection);
00901 glMatrixMode(GL_MODELVIEW);
00902 glPushMatrix();
00903 glLoadMatrixf(this->modelview);
00904 }
00905
00906 void SoFCMeshObjectShape::stopSelection(SoAction * action, const Mesh::MeshObject* mesh)
00907 {
00908
00909 glPopMatrix();
00910 glMatrixMode(GL_PROJECTION);
00911 glPopMatrix();
00912 glMatrixMode(GL_MODELVIEW);
00913 glFlush();
00914
00915
00916 GLint hits = glRenderMode(GL_RENDER);
00917
00918 unsigned int bufSize = 5*mesh->countFacets();
00919 std::vector< std::pair<double,unsigned int> > hit;
00920 GLuint index=0;
00921 for (GLint ii=0;ii<hits && index<bufSize;ii++) {
00922 GLint ct = (GLint)selectBuf[index];
00923 hit.push_back(std::pair<double,unsigned int>
00924 (selectBuf[index+1]/4294967295.0,selectBuf[index+3]));
00925 index = index+ct+3;
00926 }
00927
00928 delete [] selectBuf;
00929 selectBuf = 0;
00930 bool sorted = true;
00931 if(sorted) std::sort(hit.begin(),hit.end());
00932
00933 Gui::SoGLSelectAction *doaction = static_cast<Gui::SoGLSelectAction*>(action);
00934 doaction->indices.reserve(hit.size());
00935 for (GLint ii=0;ii<hits;ii++) {
00936 doaction->indices.push_back(hit[ii].second);
00937 }
00938 }
00939
00940 void SoFCMeshObjectShape::renderSelectionGeometry(const Mesh::MeshObject* mesh)
00941 {
00942 int fcnt=0;
00943 const MeshCore::MeshPointArray & rPoints = mesh->getKernel().GetPoints();
00944 const MeshCore::MeshFacetArray & rFacets = mesh->getKernel().GetFacets();
00945 MeshCore::MeshFacetArray::_TConstIterator it_end = rFacets.end();
00946 for (MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != it_end; ++it) {
00947 const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[0]];
00948 const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[1]];
00949 const MeshCore::MeshPoint& v2 = rPoints[it->_aulPoints[2]];
00950 glLoadName(fcnt);
00951 glBegin(GL_TRIANGLES);
00952 glVertex(v0);
00953 glVertex(v1);
00954 glVertex(v2);
00955 glEnd();
00956 fcnt++;
00957 }
00958 }
00959
00960
00961
00962
00963
00964
00965
00966
00967
00971 void
00972 SoFCMeshObjectShape::rayPick(SoRayPickAction * action)
00973 {
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983 inherited::rayPick(action);
00984 }
00985
00991 void SoFCMeshObjectShape::generatePrimitives(SoAction* action)
00992 {
00993 SoState* state = action->getState();
00994 const Mesh::MeshObject* mesh = SoFCMeshObjectElement::get(state);
00995 if (!mesh)
00996 return;
00997 const MeshCore::MeshPointArray & rPoints = mesh->getKernel().GetPoints();
00998 const MeshCore::MeshFacetArray & rFacets = mesh->getKernel().GetFacets();
00999 if (rPoints.size() < 3)
01000 return;
01001 if (rFacets.size() < 1)
01002 return;
01003
01004
01005 Binding mbind = this->findMaterialBinding(state);
01006
01007
01008 SoPrimitiveVertex vertex;
01009 SoPointDetail pointDetail;
01010 SoFaceDetail faceDetail;
01011
01012 vertex.setDetail(&pointDetail);
01013
01014 beginShape(action, TRIANGLES, &faceDetail);
01015 try
01016 {
01017 for (MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it)
01018 {
01019 const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[0]];
01020 const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[1]];
01021 const MeshCore::MeshPoint& v2 = rPoints[it->_aulPoints[2]];
01022
01023
01024 SbVec3f n;
01025 n[0] = (v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y);
01026 n[1] = (v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z);
01027 n[2] = (v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x);
01028
01029
01030 vertex.setNormal(n);
01031
01032
01033 if (mbind == PER_VERTEX_INDEXED || mbind == PER_FACE_INDEXED) {
01034 pointDetail.setMaterialIndex(it->_aulPoints[0]);
01035 vertex.setMaterialIndex(it->_aulPoints[0]);
01036 }
01037 pointDetail.setCoordinateIndex(it->_aulPoints[0]);
01038 vertex.setPoint(sbvec3f(v0));
01039 shapeVertex(&vertex);
01040
01041
01042 if (mbind == PER_VERTEX_INDEXED || mbind == PER_FACE_INDEXED) {
01043 pointDetail.setMaterialIndex(it->_aulPoints[1]);
01044 vertex.setMaterialIndex(it->_aulPoints[1]);
01045 }
01046 pointDetail.setCoordinateIndex(it->_aulPoints[1]);
01047 vertex.setPoint(sbvec3f(v1));
01048 shapeVertex(&vertex);
01049
01050
01051 if (mbind == PER_VERTEX_INDEXED || mbind == PER_FACE_INDEXED) {
01052 pointDetail.setMaterialIndex(it->_aulPoints[2]);
01053 vertex.setMaterialIndex(it->_aulPoints[2]);
01054 }
01055 pointDetail.setCoordinateIndex(it->_aulPoints[2]);
01056 vertex.setPoint(sbvec3f(v2));
01057 shapeVertex(&vertex);
01058
01059
01060 faceDetail.incFaceIndex();
01061 }
01062 }
01063 catch (const Base::MemoryException&) {
01064 Base::Console().Log("Not enough memory to generate primitives\n");
01065 }
01066
01067 endShape();
01068 }
01069
01078 SoDetail * SoFCMeshObjectShape::createTriangleDetail(SoRayPickAction * action,
01079 const SoPrimitiveVertex * v1,
01080 const SoPrimitiveVertex * v2,
01081 const SoPrimitiveVertex * v3,
01082 SoPickedPoint * pp)
01083 {
01084 SoDetail* detail = inherited::createTriangleDetail(action, v1, v2, v3, pp);
01085 return detail;
01086 }
01087
01091 void SoFCMeshObjectShape::computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er)
01092 {
01093 SoState* state = action->getState();
01094 const Mesh::MeshObject * mesh = SoFCMeshObjectElement::get(state);
01095 if (mesh && mesh->countPoints() > 0) {
01096 Base::BoundBox3f cBox = mesh->getKernel().GetBoundBox();
01097 box.setBounds(SbVec3f(cBox.MinX,cBox.MinY,cBox.MinZ),
01098 SbVec3f(cBox.MaxX,cBox.MaxY,cBox.MaxZ));
01099 Base::Vector3f mid = cBox.CalcCenter();
01100 center.setValue(mid.x,mid.y,mid.z);
01101 }
01102 else {
01103 box.setBounds(SbVec3f(0,0,0), SbVec3f(0,0,0));
01104 center.setValue(0.0f,0.0f,0.0f);
01105 }
01106 }
01107
01111 void SoFCMeshObjectShape::getPrimitiveCount(SoGetPrimitiveCountAction * action)
01112 {
01113 if (!this->shouldPrimitiveCount(action)) return;
01114 SoState* state = action->getState();
01115 const Mesh::MeshObject * mesh = SoFCMeshObjectElement::get(state);
01116 action->addNumTriangles(mesh->countFacets());
01117 action->addNumPoints(mesh->countPoints());
01118 }
01119
01123 unsigned int SoFCMeshObjectShape::countTriangles(SoAction * action) const
01124 {
01125 SoState* state = action->getState();
01126 const Mesh::MeshObject * mesh = SoFCMeshObjectElement::get(state);
01127 return (unsigned int)mesh->countFacets();
01128 }
01129
01130
01131
01132 SO_NODE_SOURCE(SoFCMeshSegmentShape);
01133
01134 void SoFCMeshSegmentShape::initClass()
01135 {
01136 SO_NODE_INIT_CLASS(SoFCMeshSegmentShape, SoShape, "Shape");
01137 }
01138
01139 SoFCMeshSegmentShape::SoFCMeshSegmentShape() : renderTriangleLimit(100000)
01140 {
01141 SO_NODE_CONSTRUCTOR(SoFCMeshSegmentShape);
01142 SO_NODE_ADD_FIELD(index, (0));
01143 }
01144
01148 void SoFCMeshSegmentShape::GLRender(SoGLRenderAction *action)
01149 {
01150 if (shouldGLRender(action))
01151 {
01152 SoState* state = action->getState();
01153
01154 SbBool mode = Gui::SoFCInteractiveElement::get(state);
01155 const Mesh::MeshObject * mesh = SoFCMeshObjectElement::get(state);
01156 if (!mesh) return;
01157
01158 Binding mbind = this->findMaterialBinding(state);
01159
01160 SoMaterialBundle mb(action);
01161
01162
01163 SbBool needNormals = !mb.isColorOnly();
01164 mb.sendFirst();
01165
01166 SbBool ccw = TRUE;
01167 if (SoShapeHintsElement::getVertexOrdering(state) == SoShapeHintsElement::CLOCKWISE)
01168 ccw = FALSE;
01169
01170 if (mode == false || mesh->countFacets() <= this->renderTriangleLimit) {
01171 if (mbind != OVERALL)
01172 drawFaces(mesh, &mb, mbind, needNormals, ccw);
01173 else
01174 drawFaces(mesh, 0, mbind, needNormals, ccw);
01175 }
01176 else {
01177 drawPoints(mesh, needNormals, ccw);
01178 }
01179
01180
01181
01182 }
01183 }
01184
01188 SoFCMeshSegmentShape::Binding SoFCMeshSegmentShape::findMaterialBinding(SoState * const state) const
01189 {
01190 Binding binding = OVERALL;
01191 SoMaterialBindingElement::Binding matbind = SoMaterialBindingElement::get(state);
01192
01193 switch (matbind) {
01194 case SoMaterialBindingElement::OVERALL:
01195 binding = OVERALL;
01196 break;
01197 case SoMaterialBindingElement::PER_VERTEX:
01198 binding = PER_VERTEX_INDEXED;
01199 break;
01200 case SoMaterialBindingElement::PER_VERTEX_INDEXED:
01201 binding = PER_VERTEX_INDEXED;
01202 break;
01203 case SoMaterialBindingElement::PER_PART:
01204 case SoMaterialBindingElement::PER_FACE:
01205 binding = PER_FACE_INDEXED;
01206 break;
01207 case SoMaterialBindingElement::PER_PART_INDEXED:
01208 case SoMaterialBindingElement::PER_FACE_INDEXED:
01209 binding = PER_FACE_INDEXED;
01210 break;
01211 default:
01212 break;
01213 }
01214 return binding;
01215 }
01216
01222 void SoFCMeshSegmentShape::drawFaces(const Mesh::MeshObject * mesh, SoMaterialBundle* mb,
01223 Binding bind, SbBool needNormals, SbBool ccw) const
01224 {
01225 const MeshCore::MeshPointArray & rPoints = mesh->getKernel().GetPoints();
01226 const MeshCore::MeshFacetArray & rFacets = mesh->getKernel().GetFacets();
01227 if (mesh->countSegments() <= this->index.getValue())
01228 return;
01229 const std::vector<unsigned long> rSegm = mesh->getSegment
01230 (this->index.getValue()).getIndices();
01231 bool perVertex = (mb && bind == PER_VERTEX_INDEXED);
01232 bool perFace = (mb && bind == PER_FACE_INDEXED);
01233
01234 if (needNormals)
01235 {
01236 glBegin(GL_TRIANGLES);
01237 if (ccw) {
01238
01239 for (std::vector<unsigned long>::const_iterator it = rSegm.begin(); it != rSegm.end(); ++it)
01240 {
01241 const MeshCore::MeshFacet& f = rFacets[*it];
01242 const MeshCore::MeshPoint& v0 = rPoints[f._aulPoints[0]];
01243 const MeshCore::MeshPoint& v1 = rPoints[f._aulPoints[1]];
01244 const MeshCore::MeshPoint& v2 = rPoints[f._aulPoints[2]];
01245
01246
01247 float n[3];
01248 n[0] = (v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y);
01249 n[1] = (v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z);
01250 n[2] = (v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x);
01251
01252 if(perFace)
01253 mb->send(*it, TRUE);
01254 glNormal(n);
01255 if(perVertex)
01256 mb->send(f._aulPoints[0], TRUE);
01257 glVertex(v0);
01258 if(perVertex)
01259 mb->send(f._aulPoints[1], TRUE);
01260 glVertex(v1);
01261 if(perVertex)
01262 mb->send(f._aulPoints[2], TRUE);
01263 glVertex(v2);
01264 }
01265 }
01266 else {
01267
01268 for (std::vector<unsigned long>::const_iterator it = rSegm.begin(); it != rSegm.end(); ++it)
01269 {
01270 const MeshCore::MeshFacet& f = rFacets[*it];
01271 const MeshCore::MeshPoint& v0 = rPoints[f._aulPoints[0]];
01272 const MeshCore::MeshPoint& v1 = rPoints[f._aulPoints[1]];
01273 const MeshCore::MeshPoint& v2 = rPoints[f._aulPoints[2]];
01274
01275
01276 float n[3];
01277 n[0] = -((v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y));
01278 n[1] = -((v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z));
01279 n[2] = -((v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x));
01280
01281 glNormal(n);
01282 glVertex(v0);
01283 glVertex(v1);
01284 glVertex(v2);
01285 }
01286 }
01287 glEnd();
01288 }
01289 else {
01290 glBegin(GL_TRIANGLES);
01291 for (std::vector<unsigned long>::const_iterator it = rSegm.begin(); it != rSegm.end(); ++it)
01292 {
01293 const MeshCore::MeshFacet& f = rFacets[*it];
01294 glVertex(rPoints[f._aulPoints[0]]);
01295 glVertex(rPoints[f._aulPoints[1]]);
01296 glVertex(rPoints[f._aulPoints[2]]);
01297 }
01298 glEnd();
01299 }
01300 }
01301
01305 void SoFCMeshSegmentShape::drawPoints(const Mesh::MeshObject * mesh, SbBool needNormals, SbBool ccw) const
01306 {
01307 const MeshCore::MeshPointArray & rPoints = mesh->getKernel().GetPoints();
01308 const MeshCore::MeshFacetArray & rFacets = mesh->getKernel().GetFacets();
01309 if (mesh->countSegments() <= this->index.getValue())
01310 return;
01311 const std::vector<unsigned long> rSegm = mesh->getSegment
01312 (this->index.getValue()).getIndices();
01313 int mod = rSegm.size()/renderTriangleLimit+1;
01314
01315 float size = std::min<float>((float)mod,3.0f);
01316 glPointSize(size);
01317
01318 if (needNormals)
01319 {
01320 glBegin(GL_POINTS);
01321 int ct=0;
01322 if (ccw) {
01323 for (std::vector<unsigned long>::const_iterator it = rSegm.begin(); it != rSegm.end(); ++it, ct++)
01324 {
01325 if (ct%mod==0) {
01326 const MeshCore::MeshFacet& f = rFacets[*it];
01327 const MeshCore::MeshPoint& v0 = rPoints[f._aulPoints[0]];
01328 const MeshCore::MeshPoint& v1 = rPoints[f._aulPoints[1]];
01329 const MeshCore::MeshPoint& v2 = rPoints[f._aulPoints[2]];
01330
01331
01332 float n[3];
01333 n[0] = (v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y);
01334 n[1] = (v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z);
01335 n[2] = (v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x);
01336
01337
01338 float p[3];
01339 p[0] = (v0.x+v1.x+v2.x)/3.0f;
01340 p[1] = (v0.y+v1.y+v2.y)/3.0f;
01341 p[2] = (v0.z+v1.z+v2.z)/3.0f;
01342 glNormal3fv(n);
01343 glVertex3fv(p);
01344 }
01345 }
01346 }
01347 else {
01348 for (std::vector<unsigned long>::const_iterator it = rSegm.begin(); it != rSegm.end(); ++it, ct++)
01349 {
01350 if (ct%mod==0) {
01351 const MeshCore::MeshFacet& f = rFacets[*it];
01352 const MeshCore::MeshPoint& v0 = rPoints[f._aulPoints[0]];
01353 const MeshCore::MeshPoint& v1 = rPoints[f._aulPoints[1]];
01354 const MeshCore::MeshPoint& v2 = rPoints[f._aulPoints[2]];
01355
01356
01357 float n[3];
01358 n[0] = -((v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y));
01359 n[1] = -((v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z));
01360 n[2] = -((v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x));
01361
01362
01363 float p[3];
01364 p[0] = (v0.x+v1.x+v2.x)/3.0f;
01365 p[1] = (v0.y+v1.y+v2.y)/3.0f;
01366 p[2] = (v0.z+v1.z+v2.z)/3.0f;
01367 glNormal3fv(n);
01368 glVertex3fv(p);
01369 }
01370 }
01371 }
01372 glEnd();
01373 }
01374 else {
01375 glBegin(GL_POINTS);
01376 int ct=0;
01377 for (std::vector<unsigned long>::const_iterator it = rSegm.begin(); it != rSegm.end(); ++it, ct++)
01378 {
01379 if (ct%mod==0) {
01380 const MeshCore::MeshFacet& f = rFacets[*it];
01381 const MeshCore::MeshPoint& v0 = rPoints[f._aulPoints[0]];
01382 const MeshCore::MeshPoint& v1 = rPoints[f._aulPoints[1]];
01383 const MeshCore::MeshPoint& v2 = rPoints[f._aulPoints[2]];
01384
01385 float p[3];
01386 p[0] = (v0.x+v1.x+v2.x)/3.0f;
01387 p[1] = (v0.y+v1.y+v2.y)/3.0f;
01388 p[2] = (v0.z+v1.z+v2.z)/3.0f;
01389 glVertex3fv(p);
01390 }
01391 }
01392 glEnd();
01393 }
01394 }
01395
01401 void SoFCMeshSegmentShape::generatePrimitives(SoAction* action)
01402 {
01403 SoState* state = action->getState();
01404 const Mesh::MeshObject* mesh = SoFCMeshObjectElement::get(state);
01405 if (!mesh)
01406 return;
01407 const MeshCore::MeshPointArray & rPoints = mesh->getKernel().GetPoints();
01408 const MeshCore::MeshFacetArray & rFacets = mesh->getKernel().GetFacets();
01409 if (rPoints.size() < 3)
01410 return;
01411 if (rFacets.size() < 1)
01412 return;
01413 if (mesh->countSegments() <= this->index.getValue())
01414 return;
01415 const std::vector<unsigned long> rSegm = mesh->getSegment
01416 (this->index.getValue()).getIndices();
01417
01418
01419 Binding mbind = this->findMaterialBinding(state);
01420
01421
01422 SoPrimitiveVertex vertex;
01423 SoPointDetail pointDetail;
01424 SoFaceDetail faceDetail;
01425
01426 vertex.setDetail(&pointDetail);
01427
01428 beginShape(action, TRIANGLES, &faceDetail);
01429 try
01430 {
01431 for (std::vector<unsigned long>::const_iterator it = rSegm.begin(); it != rSegm.end(); ++it)
01432 {
01433 const MeshCore::MeshFacet& f = rFacets[*it];
01434 const MeshCore::MeshPoint& v0 = rPoints[f._aulPoints[0]];
01435 const MeshCore::MeshPoint& v1 = rPoints[f._aulPoints[1]];
01436 const MeshCore::MeshPoint& v2 = rPoints[f._aulPoints[2]];
01437
01438
01439 SbVec3f n;
01440 n[0] = (v1.y-v0.y)*(v2.z-v0.z)-(v1.z-v0.z)*(v2.y-v0.y);
01441 n[1] = (v1.z-v0.z)*(v2.x-v0.x)-(v1.x-v0.x)*(v2.z-v0.z);
01442 n[2] = (v1.x-v0.x)*(v2.y-v0.y)-(v1.y-v0.y)*(v2.x-v0.x);
01443
01444
01445 vertex.setNormal(n);
01446
01447
01448 if (mbind == PER_VERTEX_INDEXED || mbind == PER_FACE_INDEXED) {
01449 pointDetail.setMaterialIndex(f._aulPoints[0]);
01450 vertex.setMaterialIndex(f._aulPoints[0]);
01451 }
01452 pointDetail.setCoordinateIndex(f._aulPoints[0]);
01453 vertex.setPoint(sbvec3f(v0));
01454 shapeVertex(&vertex);
01455
01456
01457 if (mbind == PER_VERTEX_INDEXED || mbind == PER_FACE_INDEXED) {
01458 pointDetail.setMaterialIndex(f._aulPoints[1]);
01459 vertex.setMaterialIndex(f._aulPoints[1]);
01460 }
01461 pointDetail.setCoordinateIndex(f._aulPoints[1]);
01462 vertex.setPoint(sbvec3f(v1));
01463 shapeVertex(&vertex);
01464
01465
01466 if (mbind == PER_VERTEX_INDEXED || mbind == PER_FACE_INDEXED) {
01467 pointDetail.setMaterialIndex(f._aulPoints[2]);
01468 vertex.setMaterialIndex(f._aulPoints[2]);
01469 }
01470 pointDetail.setCoordinateIndex(f._aulPoints[2]);
01471 vertex.setPoint(sbvec3f(v2));
01472 shapeVertex(&vertex);
01473
01474
01475 faceDetail.incFaceIndex();
01476 }
01477 }
01478 catch (const Base::MemoryException&) {
01479 Base::Console().Log("Not enough memory to generate primitives\n");
01480 }
01481
01482 endShape();
01483 }
01484
01488 void SoFCMeshSegmentShape::computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er)
01489 {
01490 box.setBounds(SbVec3f(0,0,0), SbVec3f(0,0,0));
01491 center.setValue(0.0f,0.0f,0.0f);
01492
01493 SoState* state = action->getState();
01494 const Mesh::MeshObject * mesh = SoFCMeshObjectElement::get(state);
01495 if (mesh && mesh->countSegments() > this->index.getValue()) {
01496 const Mesh::Segment& segm = mesh->getSegment(this->index.getValue());
01497 const std::vector<unsigned long>& indices = segm.getIndices();
01498 Base::BoundBox3f cBox;
01499 if (!indices.empty()) {
01500 const MeshCore::MeshPointArray& rPoint = mesh->getKernel().GetPoints();
01501 const MeshCore::MeshFacetArray& rFaces = mesh->getKernel().GetFacets();
01502
01503 for (std::vector<unsigned long>::const_iterator it = indices.begin();
01504 it != indices.end(); ++it) {
01505 const MeshCore::MeshFacet& face = rFaces[*it];
01506 cBox &= rPoint[face._aulPoints[0]];
01507 cBox &= rPoint[face._aulPoints[1]];
01508 cBox &= rPoint[face._aulPoints[2]];
01509 }
01510
01511 box.setBounds(SbVec3f(cBox.MinX,cBox.MinY,cBox.MinZ),
01512 SbVec3f(cBox.MaxX,cBox.MaxY,cBox.MaxZ));
01513 Base::Vector3f mid = cBox.CalcCenter();
01514 center.setValue(mid.x,mid.y,mid.z);
01515 }
01516 }
01517 }
01518
01522 void SoFCMeshSegmentShape::getPrimitiveCount(SoGetPrimitiveCountAction * action)
01523 {
01524 if (!this->shouldPrimitiveCount(action)) return;
01525 SoState* state = action->getState();
01526 const Mesh::MeshObject * mesh = SoFCMeshObjectElement::get(state);
01527 if (mesh && mesh->countSegments() > this->index.getValue()) {
01528 const Mesh::Segment& segm = mesh->getSegment(this->index.getValue());
01529 action->addNumTriangles(segm.getIndices().size());
01530 }
01531 }
01532
01533
01534
01535 SO_NODE_SOURCE(SoFCMeshObjectBoundary);
01536
01537 void SoFCMeshObjectBoundary::initClass()
01538 {
01539 SO_NODE_INIT_CLASS(SoFCMeshObjectBoundary, SoShape, "Shape");
01540 }
01541
01542 SoFCMeshObjectBoundary::SoFCMeshObjectBoundary()
01543 {
01544 SO_NODE_CONSTRUCTOR(SoFCMeshObjectBoundary);
01545 }
01546
01550 void SoFCMeshObjectBoundary::GLRender(SoGLRenderAction *action)
01551 {
01552 if (shouldGLRender(action))
01553 {
01554 SoState* state = action->getState();
01555 const Mesh::MeshObject * mesh = SoFCMeshObjectElement::get(state);
01556 if (!mesh) return;
01557
01558 SoMaterialBundle mb(action);
01559 SoTextureCoordinateBundle tb(action, TRUE, FALSE);
01560 SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);
01561 mb.sendFirst();
01562
01563 drawLines(mesh);
01564
01565
01566
01567 }
01568 }
01569
01573 void SoFCMeshObjectBoundary::drawLines(const Mesh::MeshObject * mesh) const
01574 {
01575 const MeshCore::MeshPointArray & rPoints = mesh->getKernel().GetPoints();
01576 const MeshCore::MeshFacetArray & rFacets = mesh->getKernel().GetFacets();
01577
01578
01579 GLfloat lineWidth;
01580 glGetFloatv(GL_LINE_WIDTH, &lineWidth);
01581 glLineWidth(3.0f*lineWidth);
01582
01583
01584
01585 glBegin(GL_LINES);
01586 for (MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it) {
01587 for (int i=0; i<3; i++) {
01588 if (it->_aulNeighbours[i] == ULONG_MAX) {
01589 glVertex(rPoints[it->_aulPoints[i]]);
01590 glVertex(rPoints[it->_aulPoints[(i+1)%3]]);
01591 }
01592 }
01593 }
01594
01595 glEnd();
01596 }
01597
01598 void SoFCMeshObjectBoundary::generatePrimitives(SoAction* action)
01599 {
01600
01601
01602 SoState* state = action->getState();
01603 const Mesh::MeshObject* mesh = SoFCMeshObjectElement::get(state);
01604 if (!mesh)
01605 return;
01606 const MeshCore::MeshPointArray & rPoints = mesh->getKernel().GetPoints();
01607 const MeshCore::MeshFacetArray & rFacets = mesh->getKernel().GetFacets();
01608
01609
01610 SoPrimitiveVertex vertex;
01611 SoPointDetail pointDetail;
01612 SoLineDetail lineDetail;
01613
01614 vertex.setDetail(&pointDetail);
01615
01616 beginShape(action, LINES, &lineDetail);
01617 for (MeshCore::MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it)
01618 {
01619 for (int i=0; i<3; i++) {
01620 if (it->_aulNeighbours[i] == ULONG_MAX) {
01621 const MeshCore::MeshPoint& v0 = rPoints[it->_aulPoints[i]];
01622 const MeshCore::MeshPoint& v1 = rPoints[it->_aulPoints[(i+1)%3]];
01623
01624
01625 pointDetail.setCoordinateIndex(it->_aulPoints[i]);
01626 vertex.setPoint(sbvec3f(v0));
01627 shapeVertex(&vertex);
01628
01629
01630 pointDetail.setCoordinateIndex(it->_aulPoints[(i+1)%3]);
01631 vertex.setPoint(sbvec3f(v1));
01632 shapeVertex(&vertex);
01633
01634
01635 lineDetail.incLineIndex();
01636 }
01637 }
01638 }
01639
01640 endShape();
01641 }
01642
01646 void SoFCMeshObjectBoundary::computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er)
01647 {
01648 SoState* state = action->getState();
01649 const Mesh::MeshObject * mesh = SoFCMeshObjectElement::get(state);
01650 if (!mesh)
01651 return;
01652 const MeshCore::MeshPointArray & rPoints = mesh->getKernel().GetPoints();
01653 if (rPoints.size() > 0) {
01654 Base::BoundBox3f cBox;
01655 for (MeshCore::MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it)
01656 cBox &= (*it);
01657 box.setBounds(SbVec3f(cBox.MinX,cBox.MinY,cBox.MinZ),
01658 SbVec3f(cBox.MaxX,cBox.MaxY,cBox.MaxZ));
01659 Base::Vector3f mid = cBox.CalcCenter();
01660 center.setValue(mid.x,mid.y,mid.z);
01661 }
01662 else {
01663 box.setBounds(SbVec3f(0,0,0), SbVec3f(0,0,0));
01664 center.setValue(0.0f,0.0f,0.0f);
01665 }
01666 }
01667
01671 void SoFCMeshObjectBoundary::getPrimitiveCount(SoGetPrimitiveCountAction * action)
01672 {
01673 if (!this->shouldPrimitiveCount(action)) return;
01674 SoState* state = action->getState();
01675 const Mesh::MeshObject * mesh = SoFCMeshObjectElement::get(state);
01676 if (!mesh)
01677 return;
01678 const MeshCore::MeshFacetArray & rFaces = mesh->getKernel().GetFacets();
01679
01680
01681 int ctEdges=0;
01682 for (MeshCore::MeshFacetArray::_TConstIterator jt = rFaces.begin(); jt != rFaces.end(); ++jt) {
01683 for (int i=0; i<3; i++) {
01684 if (jt->_aulNeighbours[i] == ULONG_MAX) {
01685 ctEdges++;
01686 }
01687 }
01688 }
01689
01690 action->addNumLines(ctEdges);
01691 }