SoBrepShape.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2011 Werner Mayer <wmayer[at]users.sourceforge.net>     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 # 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 <float.h>
00036 # include <algorithm>
00037 # include <Inventor/SoPickedPoint.h>
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/bundles/SoMaterialBundle.h>
00045 # include <Inventor/bundles/SoTextureCoordinateBundle.h>
00046 # include <Inventor/elements/SoOverrideElement.h>
00047 # include <Inventor/elements/SoCoordinateElement.h>
00048 # include <Inventor/elements/SoGLCoordinateElement.h>
00049 # include <Inventor/elements/SoGLCacheContextElement.h>
00050 # include <Inventor/elements/SoLineWidthElement.h>
00051 # include <Inventor/elements/SoPointSizeElement.h>
00052 # include <Inventor/errors/SoReadError.h>
00053 # include <Inventor/details/SoFaceDetail.h>
00054 # include <Inventor/details/SoLineDetail.h>
00055 # include <Inventor/misc/SoState.h>
00056 #endif
00057 
00058 #include "SoBrepShape.h"
00059 #include <Gui/SoFCUnifiedSelection.h>
00060 #include <Gui/SoFCSelectionAction.h>
00061 
00062 using namespace PartGui;
00063 
00064 
00065 SO_NODE_SOURCE(SoBrepFaceSet);
00066 
00067 void SoBrepFaceSet::initClass()
00068 {
00069     SO_NODE_INIT_CLASS(SoBrepFaceSet, SoIndexedFaceSet, "IndexedFaceSet");
00070 }
00071 
00072 SoBrepFaceSet::SoBrepFaceSet()
00073 {
00074     SO_NODE_CONSTRUCTOR(SoBrepFaceSet);
00075     SO_NODE_ADD_FIELD(partIndex, (-1));
00076     SO_NODE_ADD_FIELD(highlightIndex, (-1));
00077     SO_NODE_ADD_FIELD(selectionIndex, (-1));
00078     selectionIndex.setNum(0);
00079 }
00080 
00081 void SoBrepFaceSet::doAction(SoAction* action)
00082 {
00083     if (action->getTypeId() == Gui::SoHighlightElementAction::getClassTypeId()) {
00084         Gui::SoHighlightElementAction* hlaction = static_cast<Gui::SoHighlightElementAction*>(action);
00085         if (!hlaction->isHighlighted()) {
00086             this->highlightIndex = -1;
00087             return;
00088         }
00089 
00090         const SoPickedPoint* pp = hlaction->getElement();
00091         if (pp && pp->getDetail()) {
00092             const SoDetail* detail = pp->getDetail();
00093             if (detail->isOfType(SoFaceDetail::getClassTypeId())) {
00094                 int index = static_cast<const SoFaceDetail*>(detail)->getPartIndex();
00095                 this->highlightIndex.setValue(index);
00096                 this->highlightColor = hlaction->getColor();
00097             }
00098             else {
00099                 this->highlightIndex = -1;
00100                 return;
00101             }
00102         }
00103     }
00104     else if (action->getTypeId() == Gui::SoSelectionElementAction::getClassTypeId()) {
00105         Gui::SoSelectionElementAction* selaction = static_cast<Gui::SoSelectionElementAction*>(action);
00106         this->selectionColor = selaction->getColor();
00107         if (selaction->getType() == Gui::SoSelectionElementAction::All) {
00108             int num = this->partIndex.getNum();
00109             this->selectionIndex.setNum(num);
00110             int32_t* v = this->selectionIndex.startEditing();
00111             for (int i=0; i<num;i++)
00112                 v[i] = i;
00113             this->selectionIndex.finishEditing();
00114             return;
00115         }
00116         else if (selaction->getType() == Gui::SoSelectionElementAction::None) {
00117             this->selectionIndex.setNum(0);
00118             return;
00119         }
00120 
00121         const SoPickedPoint* pp = selaction->getElement();
00122         if (pp && pp->getDetail()) {
00123             const SoDetail* detail = pp->getDetail();
00124 
00125             if (!detail->isOfType(SoFaceDetail::getClassTypeId())) {
00126                 return;
00127             }
00128 
00129             int index = static_cast<const SoFaceDetail*>(detail)->getPartIndex();
00130             switch (selaction->getType()) {
00131             case Gui::SoSelectionElementAction::Append:
00132                 {
00133                     int start = this->selectionIndex.getNum();
00134                     this->selectionIndex.set1Value(start, index);
00135                 }
00136                 break;
00137             case Gui::SoSelectionElementAction::Remove:
00138                 {
00139                     int start = this->selectionIndex.find(index);
00140                     this->selectionIndex.deleteValues(start,1);
00141                 }
00142                 break;
00143             default:
00144                 break;
00145             }
00146         }
00147     }
00148 
00149     inherited::doAction(action);
00150 }
00151 
00152 void SoBrepFaceSet::GLRender(SoGLRenderAction *action)
00153 {
00154     if (this->coordIndex.getNum() < 3)
00155         return;
00156     if (this->selectionIndex.getNum() > 0)
00157         renderSelection(action);
00158     if (this->highlightIndex.getValue() >= 0)
00159         renderHighlight(action);
00160     if (!this->shouldGLRender(action))
00161         return;
00162 
00163     SoState * state = action->getState();
00164 
00165     Binding mbind = this->findMaterialBinding(state);
00166     Binding nbind = this->findNormalBinding(state);
00167 
00168     const SoCoordinateElement * coords;
00169     const SbVec3f * normals;
00170     const int32_t * cindices;
00171     int numindices;
00172     const int32_t * nindices;
00173     const int32_t * tindices;
00174     const int32_t * mindices;
00175     const int32_t * pindices;
00176     int numparts;
00177     SbBool doTextures;
00178     SbBool normalCacheUsed;
00179 
00180     SoMaterialBundle mb(action);
00181 
00182     SoTextureCoordinateBundle tb(action, TRUE, FALSE);
00183     doTextures = tb.needCoordinates();
00184     SbBool sendNormals = !mb.isColorOnly() || tb.isFunction();
00185 
00186     this->getVertexData(state, coords, normals, cindices,
00187                         nindices, tindices, mindices, numindices,
00188                         sendNormals, normalCacheUsed);
00189 
00190     mb.sendFirst(); // make sure we have the correct material
00191 
00192     // just in case someone forgot
00193     if (!mindices) mindices = cindices;
00194     if (!nindices) nindices = cindices;
00195     pindices = this->partIndex.getValues(0);
00196     numparts = this->partIndex.getNum();
00197     renderShape(static_cast<const SoGLCoordinateElement*>(coords), cindices, numindices,
00198         pindices, numparts, normals, nindices, &mb, mindices, &tb, tindices, nbind, mbind, doTextures?1:0);
00199     // Disable caching for this node
00200     SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE);
00201 
00202     // Workaround for #0000433
00203 //#if !defined(FC_OS_WIN32)
00204     if (this->highlightIndex.getValue() >= 0)
00205         renderHighlight(action);
00206     if (this->selectionIndex.getNum() > 0)
00207         renderSelection(action);
00208 //#endif
00209 }
00210 
00211 void SoBrepFaceSet::GLRenderBelowPath(SoGLRenderAction * action)
00212 {
00213     inherited::GLRenderBelowPath(action);
00214 }
00215 
00216 void SoBrepFaceSet::renderHighlight(SoGLRenderAction *action)
00217 {
00218     SoState * state = action->getState();
00219     state->push();
00220 
00221     SoLazyElement::setEmissive(state, &this->highlightColor);
00222     SoOverrideElement::setEmissiveColorOverride(state, this, TRUE);
00223 #if 0 // disables shading effect
00224     // sendNormals will be FALSE
00225     SoLazyElement::setDiffuse(state, this,1, &this->highlightColor,&this->colorpacker);
00226     SoOverrideElement::setDiffuseColorOverride(state, this, TRUE);
00227     SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);
00228 #endif
00229 
00230     Binding mbind = this->findMaterialBinding(state);
00231     Binding nbind = this->findNormalBinding(state);
00232 
00233     const SoCoordinateElement * coords;
00234     const SbVec3f * normals;
00235     const int32_t * cindices;
00236     int numindices;
00237     const int32_t * nindices;
00238     const int32_t * tindices;
00239     const int32_t * mindices;
00240     const int32_t * pindices;
00241     SbBool doTextures;
00242     SbBool normalCacheUsed;
00243 
00244     SoMaterialBundle mb(action);
00245     SoTextureCoordinateBundle tb(action, TRUE, FALSE);
00246     doTextures = tb.needCoordinates();
00247     SbBool sendNormals = !mb.isColorOnly() || tb.isFunction();
00248 
00249     this->getVertexData(state, coords, normals, cindices,
00250                         nindices, tindices, mindices, numindices,
00251                         sendNormals, normalCacheUsed);
00252 
00253     mb.sendFirst(); // make sure we have the correct material
00254 
00255     int32_t id = this->highlightIndex.getValue();
00256 
00257     // just in case someone forgot
00258     if (!mindices) mindices = cindices;
00259     if (!nindices) nindices = cindices;
00260     pindices = this->partIndex.getValues(0);
00261 
00262     // coords
00263     int length = (int)pindices[id]*4;
00264     int start=0;
00265     for (int i=0;i<id;i++)
00266         start+=(int)pindices[i];
00267     start *= 4;
00268 
00269     // normals
00270     if (nbind == PER_VERTEX_INDEXED)
00271         nindices = &(nindices[start]);
00272     else if (nbind == PER_VERTEX)
00273         normals = &(normals[start]);
00274     else 
00275         nbind = OVERALL;
00276 
00277     // materials
00278     mbind = OVERALL;
00279     doTextures = FALSE;
00280 
00281     renderShape(static_cast<const SoGLCoordinateElement*>(coords), &(cindices[start]), length,
00282         &(pindices[id]), 1, normals, nindices, &mb, mindices, &tb, tindices, nbind, mbind, doTextures?1:0);
00283     state->pop();
00284 }
00285 
00286 void SoBrepFaceSet::renderSelection(SoGLRenderAction *action)
00287 {
00288     int numSelected =  this->selectionIndex.getNum();
00289     const int32_t* selected = this->selectionIndex.getValues(0);
00290     if (numSelected == 0) return;
00291 
00292     SoState * state = action->getState();
00293     state->push();
00294 
00295     SoLazyElement::setEmissive(state, &this->selectionColor);
00296     SoOverrideElement::setEmissiveColorOverride(state, this, TRUE);
00297 #if 0 // disables shading effect
00298     SoLazyElement::setDiffuse(state, this,1, &this->selectionColor,&this->colorpacker);
00299     SoOverrideElement::setDiffuseColorOverride(state, this, TRUE);
00300     SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);
00301 #endif
00302 
00303     Binding mbind = this->findMaterialBinding(state);
00304     Binding nbind = this->findNormalBinding(state);
00305 
00306     const SoCoordinateElement * coords;
00307     const SbVec3f * normals;
00308     const int32_t * cindices;
00309     int numindices;
00310     const int32_t * nindices;
00311     const int32_t * tindices;
00312     const int32_t * mindices;
00313     const int32_t * pindices;
00314     SbBool doTextures;
00315     SbBool normalCacheUsed;
00316 
00317     SoMaterialBundle mb(action);
00318     SoTextureCoordinateBundle tb(action, TRUE, FALSE);
00319     doTextures = tb.needCoordinates();
00320     SbBool sendNormals = !mb.isColorOnly() || tb.isFunction();
00321 
00322     this->getVertexData(state, coords, normals, cindices,
00323                         nindices, tindices, mindices, numindices,
00324                         sendNormals, normalCacheUsed);
00325 
00326     mb.sendFirst(); // make sure we have the correct material
00327 
00328     // just in case someone forgot
00329     if (!mindices) mindices = cindices;
00330     if (!nindices) nindices = cindices;
00331     pindices = this->partIndex.getValues(0);
00332 
00333     // materials
00334     mbind = OVERALL;
00335     doTextures = FALSE;
00336 
00337     for (int i=0; i<numSelected; i++) {
00338         int id = selected[i];
00339 
00340         // coords
00341         int length = (int)pindices[id]*4;
00342         int start=0;
00343         for (int j=0;j<id;j++)
00344             start+=(int)pindices[j];
00345         start *= 4;
00346 
00347         // normals
00348         const SbVec3f * normals_s = normals;
00349         const int32_t * nindices_s = nindices;
00350         if (nbind == PER_VERTEX_INDEXED)
00351             nindices_s = &(nindices[start]);
00352         else if (nbind == PER_VERTEX)
00353             normals_s = &(normals[start]);
00354         else 
00355             nbind = OVERALL;
00356 
00357         renderShape(static_cast<const SoGLCoordinateElement*>(coords), &(cindices[start]), length,
00358             &(pindices[id]), 1, normals_s, nindices_s, &mb, mindices, &tb, tindices, nbind, mbind, doTextures?1:0);
00359     }
00360     state->pop();
00361 }
00362 
00363 void SoBrepFaceSet::renderShape(const SoGLCoordinateElement * const vertexlist,
00364                                 const int32_t *vertexindices,
00365                                 int numindices,
00366                                 const int32_t *partindices,
00367                                 int num_partindices,
00368                                 const SbVec3f *normals,
00369                                 const int32_t *normalindices,
00370                                 SoMaterialBundle *const materials,
00371                                 const int32_t *matindices,
00372                                 SoTextureCoordinateBundle * const texcoords,
00373                                 const int32_t *texindices,
00374                                 const int nbind,
00375                                 const int mbind,
00376                                 const int texture)
00377 {
00378     int texidx = 0;
00379 
00380     const SbVec3f * coords3d = NULL;
00381     coords3d = vertexlist->getArrayPtr3();
00382 
00383     const int32_t *viptr = vertexindices;
00384     const int32_t *viendptr = viptr + numindices;
00385     const int32_t *piptr = partindices;
00386     const int32_t *piendptr = piptr + num_partindices;
00387     int32_t v1, v2, v3, v4, pi;
00388     SbVec3f dummynormal(0,0,1);
00389     int numverts = vertexlist->getNum();
00390 
00391     const SbVec3f *currnormal = &dummynormal;
00392     if (normals) currnormal = normals;
00393 
00394     int matnr = 0;
00395     int trinr = 0;
00396     pi = piptr < piendptr ? *piptr++ : -1;
00397 
00398     glBegin(GL_TRIANGLES);
00399     while (viptr + 2 < viendptr) {
00400         v1 = *viptr++;
00401         v2 = *viptr++;
00402         v3 = *viptr++;
00403 
00404         // This test is for robustness upon buggy data sets
00405         if (v1 < 0 || v2 < 0 || v3 < 0 ||
00406             v1 >= numverts || v2 >= numverts || v3 >= numverts) {
00407             break;
00408         }
00409         v4 = viptr < viendptr ? *viptr++ : -1;
00410 
00411         /* vertex 1 *********************************************************/
00412         if (mbind == PER_PART) {
00413             if (trinr == 0)
00414                 materials->send(matnr++, TRUE);
00415         }
00416         else if (mbind == PER_PART_INDEXED) {
00417             if (trinr == 0)
00418                 materials->send(*matindices++, TRUE);
00419         }
00420         else if (mbind == PER_VERTEX || mbind == PER_FACE) {
00421             materials->send(matnr++, TRUE);
00422         }
00423         else if (mbind == PER_VERTEX_INDEXED || mbind == PER_FACE_INDEXED) {
00424             materials->send(*matindices++, TRUE);
00425         }
00426 
00427         if (normals) {
00428             if (nbind == PER_VERTEX || nbind == PER_FACE) {
00429                 currnormal = normals++;
00430                 glNormal3fv((const GLfloat*)currnormal);
00431             }
00432             else if (nbind == PER_VERTEX_INDEXED || nbind == PER_FACE_INDEXED) {
00433                 currnormal = &normals[*normalindices++];
00434                 glNormal3fv((const GLfloat*)currnormal);
00435             }
00436         }
00437 
00438         if (texture) {
00439             texcoords->send(texindices ? *texindices++ : texidx++,
00440                         vertexlist->get3(v1),
00441                         *currnormal);
00442         }
00443 
00444         glVertex3fv((const GLfloat*) (coords3d + v1));
00445 
00446         /* vertex 2 *********************************************************/
00447         if (mbind == PER_VERTEX)
00448             materials->send(matnr++, TRUE);
00449         else if (mbind == PER_VERTEX_INDEXED)
00450             materials->send(*matindices++, TRUE);
00451 
00452         if (normals) {
00453             if (nbind == PER_VERTEX) {
00454                 currnormal = normals++;
00455                 glNormal3fv((const GLfloat*)currnormal);
00456             }
00457             else if (nbind == PER_VERTEX_INDEXED) {
00458                 currnormal = &normals[*normalindices++];
00459                 glNormal3fv((const GLfloat*)currnormal);
00460             }
00461         }
00462 
00463         if (texture) {
00464             texcoords->send(texindices ? *texindices++ : texidx++,
00465                             vertexlist->get3(v2),
00466                             *currnormal);
00467         }
00468 
00469         glVertex3fv((const GLfloat*) (coords3d + v2));
00470 
00471         /* vertex 3 *********************************************************/
00472         if (mbind == PER_VERTEX)
00473             materials->send(matnr++, TRUE);
00474         else if (mbind == PER_VERTEX_INDEXED)
00475             materials->send(*matindices++, TRUE);
00476 
00477         if (normals) {
00478             if (nbind == PER_VERTEX) {
00479                 currnormal = normals++;
00480                 glNormal3fv((const GLfloat*)currnormal);
00481             }
00482             else if (nbind == PER_VERTEX_INDEXED) {
00483                 currnormal = &normals[*normalindices++];
00484                 glNormal3fv((const GLfloat*)currnormal);
00485             }
00486         }
00487 
00488         if (texture) {
00489             texcoords->send(texindices ? *texindices++ : texidx++,
00490                             vertexlist->get3(v3),
00491                             *currnormal);
00492         }
00493 
00494         glVertex3fv((const GLfloat*) (coords3d + v3));
00495 
00496         if (mbind == PER_VERTEX_INDEXED)
00497             matindices++;
00498 
00499         if (nbind == PER_VERTEX_INDEXED)
00500             normalindices++;
00501 
00502         if (texture && texindices) {
00503             texindices++;
00504         }
00505 
00506         trinr++;
00507         if (pi == trinr) {
00508             pi = piptr < piendptr ? *piptr++ : -1;
00509             trinr = 0;
00510         }
00511     }
00512     glEnd();
00513 }
00514 
00515 SoDetail * SoBrepFaceSet::createTriangleDetail(SoRayPickAction * action,
00516                                                const SoPrimitiveVertex * v1,
00517                                                const SoPrimitiveVertex * v2,
00518                                                const SoPrimitiveVertex * v3,
00519                                                SoPickedPoint * pp)
00520 {
00521     SoDetail* detail = inherited::createTriangleDetail(action, v1, v2, v3, pp);
00522     const int32_t * indices = this->partIndex.getValues(0);
00523     int num = this->partIndex.getNum();
00524     if (indices) {
00525         SoFaceDetail* face_detail = static_cast<SoFaceDetail*>(detail);
00526         int index = face_detail->getFaceIndex();
00527         int count = 0;
00528         for (int i=0; i<num; i++) {
00529             count += indices[i];
00530             if (index < count) {
00531                 face_detail->setPartIndex(i);
00532                 break;
00533             }
00534         }
00535     }
00536     return detail;
00537 }
00538 
00539 SoBrepFaceSet::Binding
00540 SoBrepFaceSet::findMaterialBinding(SoState * const state) const
00541 {
00542     Binding binding = OVERALL;
00543     SoMaterialBindingElement::Binding matbind =
00544         SoMaterialBindingElement::get(state);
00545 
00546     switch (matbind) {
00547     case SoMaterialBindingElement::OVERALL:
00548         binding = OVERALL;
00549         break;
00550     case SoMaterialBindingElement::PER_VERTEX:
00551         binding = PER_VERTEX;
00552         break;
00553     case SoMaterialBindingElement::PER_VERTEX_INDEXED:
00554         binding = PER_VERTEX_INDEXED;
00555         break;
00556     case SoMaterialBindingElement::PER_PART:
00557         binding = PER_PART;
00558         break;
00559     case SoMaterialBindingElement::PER_FACE:
00560         binding = PER_FACE;
00561         break;
00562     case SoMaterialBindingElement::PER_PART_INDEXED:
00563         binding = PER_PART_INDEXED;
00564         break;
00565     case SoMaterialBindingElement::PER_FACE_INDEXED:
00566         binding = PER_FACE_INDEXED;
00567         break;
00568     default:
00569         break;
00570     }
00571     return binding;
00572 }
00573 
00574 SoBrepFaceSet::Binding
00575 SoBrepFaceSet::findNormalBinding(SoState * const state) const
00576 {
00577     Binding binding = PER_VERTEX_INDEXED;
00578     SoNormalBindingElement::Binding normbind =
00579         (SoNormalBindingElement::Binding) SoNormalBindingElement::get(state);
00580 
00581     switch (normbind) {
00582     case SoNormalBindingElement::OVERALL:
00583         binding = OVERALL;
00584         break;
00585     case SoNormalBindingElement::PER_VERTEX:
00586         binding = PER_VERTEX;
00587         break;
00588     case SoNormalBindingElement::PER_VERTEX_INDEXED:
00589         binding = PER_VERTEX_INDEXED;
00590         break;
00591     case SoNormalBindingElement::PER_PART:
00592         binding = PER_PART;
00593         break;
00594     case SoNormalBindingElement::PER_FACE:
00595         binding = PER_FACE;
00596         break;
00597     case SoNormalBindingElement::PER_PART_INDEXED:
00598         binding = PER_PART_INDEXED;
00599         break;
00600     case SoNormalBindingElement::PER_FACE_INDEXED:
00601         binding = PER_FACE_INDEXED;
00602         break;
00603     default:
00604         break;
00605     }
00606     return binding;
00607 }
00608 
00609 // ---------------------------------------------------------------------
00610 
00611 SO_NODE_SOURCE(SoBrepEdgeSet);
00612 
00613 void SoBrepEdgeSet::initClass()
00614 {
00615     SO_NODE_INIT_CLASS(SoBrepEdgeSet, SoIndexedLineSet, "IndexedLineSet");
00616 }
00617 
00618 SoBrepEdgeSet::SoBrepEdgeSet()
00619 {
00620     SO_NODE_CONSTRUCTOR(SoBrepEdgeSet);
00621     SO_NODE_ADD_FIELD(highlightIndex, (-1));
00622     SO_NODE_ADD_FIELD(selectionIndex, (-1));
00623     selectionIndex.setNum(0);
00624 }
00625 
00626 void SoBrepEdgeSet::GLRender(SoGLRenderAction *action)
00627 {
00628     if (this->selectionIndex.getNum() > 0)
00629         renderSelection(action);
00630     if (this->highlightIndex.getValue() >= 0)
00631         renderHighlight(action);
00632     inherited::GLRender(action);
00633 
00634     // Workaround for #0000433
00635 //#if !defined(FC_OS_WIN32)
00636     if (this->highlightIndex.getValue() >= 0)
00637         renderHighlight(action);
00638     if (this->selectionIndex.getNum() > 0)
00639         renderSelection(action);
00640 //#endif
00641 }
00642 
00643 void SoBrepEdgeSet::GLRenderBelowPath(SoGLRenderAction * action)
00644 {
00645     inherited::GLRenderBelowPath(action);
00646 }
00647 
00648 void SoBrepEdgeSet::renderShape(const SoGLCoordinateElement * const coords,
00649                                 const int32_t *cindices, int numindices)
00650 {
00651 
00652     const SbVec3f * coords3d = coords->getArrayPtr3();
00653 
00654     int32_t i;
00655     int previ;
00656     const int32_t *end = cindices + numindices;
00657     while (cindices < end) {
00658         glBegin(GL_LINE_STRIP);
00659         previ = *cindices++;
00660         i = (cindices < end) ? *cindices++ : -1;
00661         while (i >= 0) {
00662             glVertex3fv((const GLfloat*) (coords3d + previ));
00663             glVertex3fv((const GLfloat*) (coords3d + i));
00664             previ = i;
00665             i = cindices < end ? *cindices++ : -1;
00666         }
00667         glEnd();
00668     }
00669 }
00670 
00671 void SoBrepEdgeSet::renderHighlight(SoGLRenderAction *action)
00672 {
00673     SoState * state = action->getState();
00674     state->push();
00675   //SoLineWidthElement::set(state, this, 4.0f);
00676 
00677     SoLazyElement::setEmissive(state, &this->highlightColor);
00678     SoOverrideElement::setEmissiveColorOverride(state, this, TRUE);
00679     SoLazyElement::setDiffuse(state, this,1, &this->highlightColor,&this->colorpacker);
00680     SoOverrideElement::setDiffuseColorOverride(state, this, TRUE);
00681     SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);
00682 
00683     const SoCoordinateElement * coords;
00684     const SbVec3f * normals;
00685     const int32_t * cindices;
00686     int numcindices;
00687     const int32_t * nindices;
00688     const int32_t * tindices;
00689     const int32_t * mindices;
00690     SbBool normalCacheUsed;
00691 
00692     this->getVertexData(state, coords, normals, cindices, nindices,
00693         tindices, mindices, numcindices, FALSE, normalCacheUsed);
00694 
00695     SoMaterialBundle mb(action);
00696     mb.sendFirst(); // make sure we have the correct material
00697 
00698     const int32_t* id = &(this->hl[0]);
00699     int num = (int)this->hl.size();
00700 
00701     renderShape(static_cast<const SoGLCoordinateElement*>(coords), id, num);
00702     state->pop();
00703 }
00704 
00705 void SoBrepEdgeSet::renderSelection(SoGLRenderAction *action)
00706 {
00707     int numSelected =  this->selectionIndex.getNum();
00708     if (numSelected == 0) return;
00709 
00710     SoState * state = action->getState();
00711     state->push();
00712   //SoLineWidthElement::set(state, this, 4.0f);
00713 
00714     SoLazyElement::setEmissive(state, &this->selectionColor);
00715     SoOverrideElement::setEmissiveColorOverride(state, this, TRUE);
00716     SoLazyElement::setDiffuse(state, this,1, &this->selectionColor,&this->colorpacker);
00717     SoOverrideElement::setDiffuseColorOverride(state, this, TRUE);
00718     SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);
00719 
00720     const SoCoordinateElement * coords;
00721     const SbVec3f * normals;
00722     const int32_t * cindices;
00723     int numcindices;
00724     const int32_t * nindices;
00725     const int32_t * tindices;
00726     const int32_t * mindices;
00727     SbBool normalCacheUsed;
00728 
00729     this->getVertexData(state, coords, normals, cindices, nindices,
00730         tindices, mindices, numcindices, FALSE, normalCacheUsed);
00731 
00732     SoMaterialBundle mb(action);
00733     mb.sendFirst(); // make sure we have the correct material
00734 
00735     cindices = &(this->sl[0]);
00736     numcindices = (int)this->sl.size();
00737 
00738     renderShape(static_cast<const SoGLCoordinateElement*>(coords), cindices, numcindices);
00739     state->pop();
00740 }
00741 
00742 static void createIndexArray(const int32_t* segm, int numsegm,
00743                              const int32_t* cindices, int numcindices,
00744                              std::vector<int32_t>& out)
00745 {
00746     std::vector<int32_t> v;
00747     for (int j=0; j<numsegm; j++) {
00748         int index = segm[j];
00749         int start=0, num=0;
00750         int section=0;
00751         for (int i=0;i<numcindices;i++) {
00752             if (section < index)
00753                 start++;
00754             else if (section == index)
00755                 num++;
00756             else if (section > index)
00757                 break;
00758             if (cindices[i] < 0)
00759                 section++;
00760         }
00761 
00762         v.insert(v.end(), cindices+start, cindices+start+num);
00763     }
00764 
00765     out.swap(v);
00766 }
00767 
00768 void SoBrepEdgeSet::doAction(SoAction* action)
00769 {
00770     if (action->getTypeId() == Gui::SoHighlightElementAction::getClassTypeId()) {
00771         Gui::SoHighlightElementAction* hlaction = static_cast<Gui::SoHighlightElementAction*>(action);
00772         if (!hlaction->isHighlighted()) {
00773             this->highlightIndex = -1;
00774             this->hl.clear();
00775             return;
00776         }
00777         const SoPickedPoint* pp = hlaction->getElement();
00778         if (pp && pp->getDetail()) {
00779             const SoDetail* detail = pp->getDetail();
00780             if (!detail->isOfType(SoLineDetail::getClassTypeId())) {
00781                 this->highlightIndex = -1;
00782                 this->hl.clear();
00783                 return;
00784             }
00785 
00786             this->highlightColor = hlaction->getColor();
00787             int32_t index = static_cast<const SoLineDetail*>(detail)->getLineIndex();
00788             const int32_t* cindices = this->coordIndex.getValues(0);
00789             int numcindices = this->coordIndex.getNum();
00790 
00791             createIndexArray(&index, 1, cindices, numcindices, this->hl);
00792             this->highlightIndex.setValue(index);
00793         }
00794     }
00795     else if (action->getTypeId() == Gui::SoSelectionElementAction::getClassTypeId()) {
00796         Gui::SoSelectionElementAction* selaction = static_cast<Gui::SoSelectionElementAction*>(action);
00797 
00798         this->selectionColor = selaction->getColor();
00799         if (selaction->getType() == Gui::SoSelectionElementAction::All) {
00800             const int32_t* cindices = this->coordIndex.getValues(0);
00801             int numcindices = this->coordIndex.getNum();
00802             unsigned int num = std::count_if(cindices, cindices+numcindices, 
00803                 std::bind2nd(std::equal_to<int32_t>(), -1));
00804 
00805             this->sl.clear();
00806             this->selectionIndex.setNum(num);
00807             int32_t* v = this->selectionIndex.startEditing();
00808             for (unsigned int i=0; i<num;i++)
00809                 v[i] = i;
00810             this->selectionIndex.finishEditing();
00811 
00812             int numsegm = this->selectionIndex.getNum();
00813             if (numsegm > 0) {
00814                 const int32_t* selsegm = this->selectionIndex.getValues(0);
00815                 const int32_t* cindices = this->coordIndex.getValues(0);
00816                 int numcindices = this->coordIndex.getNum();
00817                 createIndexArray(selsegm, numsegm, cindices, numcindices, this->sl);
00818             }
00819             return;
00820         }
00821         else if (selaction->getType() == Gui::SoSelectionElementAction::None) {
00822             this->selectionIndex.setNum(0);
00823             this->sl.clear();
00824             return;
00825         }
00826 
00827         const SoPickedPoint* pp = selaction->getElement();
00828         if (pp && pp->getDetail()) {
00829             const SoDetail* detail = pp->getDetail();
00830             if (!detail->isOfType(SoLineDetail::getClassTypeId())) {
00831                 return;
00832             }
00833 
00834             int index = static_cast<const SoLineDetail*>(detail)->getLineIndex();
00835             switch (selaction->getType()) {
00836             case Gui::SoSelectionElementAction::Append:
00837                 {
00838                     int start = this->selectionIndex.getNum();
00839                     this->selectionIndex.set1Value(start, index);
00840                 }
00841                 break;
00842             case Gui::SoSelectionElementAction::Remove:
00843                 {
00844                     int start = this->selectionIndex.find(index);
00845                     this->selectionIndex.deleteValues(start,1);
00846                 }
00847                 break;
00848             default:
00849                 break;
00850             }
00851 
00852             int numsegm = this->selectionIndex.getNum();
00853             if (numsegm > 0) {
00854                 const int32_t* selsegm = this->selectionIndex.getValues(0);
00855                 const int32_t* cindices = this->coordIndex.getValues(0);
00856                 int numcindices = this->coordIndex.getNum();
00857                 createIndexArray(selsegm, numsegm, cindices, numcindices, this->sl);
00858             }
00859         }
00860     }
00861 
00862     inherited::doAction(action);
00863 }
00864 
00865 SoDetail * SoBrepEdgeSet::createLineSegmentDetail(SoRayPickAction * action,
00866                                                   const SoPrimitiveVertex * v1,
00867                                                   const SoPrimitiveVertex * v2,
00868                                                   SoPickedPoint * pp)
00869 {
00870     SoDetail* detail = inherited::createLineSegmentDetail(action, v1, v2, pp);
00871     SoLineDetail* line_detail = static_cast<SoLineDetail*>(detail);
00872     int index = line_detail->getLineIndex();
00873     line_detail->setPartIndex(index);
00874     return detail;
00875 }
00876 
00877 // ---------------------------------------------------------------------
00878 
00879 SO_NODE_SOURCE(SoBrepPointSet);
00880 
00881 void SoBrepPointSet::initClass()
00882 {
00883     SO_NODE_INIT_CLASS(SoBrepPointSet, SoPointSet, "PointSet");
00884 }
00885 
00886 SoBrepPointSet::SoBrepPointSet()
00887 {
00888     SO_NODE_CONSTRUCTOR(SoBrepPointSet);
00889     SO_NODE_ADD_FIELD(highlightIndex, (-1));
00890     SO_NODE_ADD_FIELD(selectionIndex, (-1));
00891     selectionIndex.setNum(0);
00892 }
00893 
00894 void SoBrepPointSet::GLRender(SoGLRenderAction *action)
00895 {
00896     if (this->selectionIndex.getNum() > 0)
00897         renderSelection(action);
00898     if (this->highlightIndex.getValue() >= 0)
00899         renderHighlight(action);
00900     inherited::GLRender(action);
00901 
00902     // Workaround for #0000433
00903 //#if !defined(FC_OS_WIN32)
00904     if (this->highlightIndex.getValue() >= 0)
00905         renderHighlight(action);
00906     if (this->selectionIndex.getNum() > 0)
00907         renderSelection(action);
00908 //#endif
00909 }
00910 
00911 void SoBrepPointSet::GLRenderBelowPath(SoGLRenderAction * action)
00912 {
00913     inherited::GLRenderBelowPath(action);
00914 }
00915 
00916 void SoBrepPointSet::renderShape(const SoGLCoordinateElement * const coords, 
00917                                  const int32_t *cindices,
00918                                  int numindices)
00919 {
00920     const SbVec3f * coords3d = coords->getArrayPtr3();
00921 
00922     int previ;
00923     const int32_t *end = cindices + numindices;
00924     glBegin(GL_POINTS);
00925     while (cindices < end) {
00926         previ = *cindices++;
00927         glVertex3fv((const GLfloat*) (coords3d + previ));
00928     }
00929     glEnd();
00930 }
00931 
00932 void SoBrepPointSet::renderHighlight(SoGLRenderAction *action)
00933 {
00934     SoState * state = action->getState();
00935     state->push();
00936     float ps = SoPointSizeElement::get(state);
00937     if (ps < 4.0f) SoPointSizeElement::set(state, this, 4.0f);
00938 
00939     SoLazyElement::setEmissive(state, &this->highlightColor);
00940     SoOverrideElement::setEmissiveColorOverride(state, this, TRUE);
00941     SoLazyElement::setDiffuse(state, this,1, &this->highlightColor,&this->colorpacker);
00942     SoOverrideElement::setDiffuseColorOverride(state, this, TRUE);
00943 
00944     const SoCoordinateElement * coords;
00945     const SbVec3f * normals;
00946 
00947     this->getVertexData(state, coords, normals, FALSE);
00948 
00949     SoMaterialBundle mb(action);
00950     mb.sendFirst(); // make sure we have the correct material
00951 
00952     int32_t id = this->highlightIndex.getValue();
00953 
00954     renderShape(static_cast<const SoGLCoordinateElement*>(coords), &id, 1);
00955     state->pop();
00956 }
00957 
00958 void SoBrepPointSet::renderSelection(SoGLRenderAction *action)
00959 {
00960     SoState * state = action->getState();
00961     state->push();
00962     float ps = SoPointSizeElement::get(state);
00963     if (ps < 4.0f) SoPointSizeElement::set(state, this, 4.0f);
00964 
00965     SoLazyElement::setEmissive(state, &this->selectionColor);
00966     SoOverrideElement::setEmissiveColorOverride(state, this, TRUE);
00967     SoLazyElement::setDiffuse(state, this,1, &this->selectionColor,&this->colorpacker);
00968     SoOverrideElement::setDiffuseColorOverride(state, this, TRUE);
00969 
00970     const SoCoordinateElement * coords;
00971     const SbVec3f * normals;
00972     const int32_t * cindices;
00973     int numcindices;
00974 
00975     this->getVertexData(state, coords, normals, FALSE);
00976 
00977     SoMaterialBundle mb(action);
00978     mb.sendFirst(); // make sure we have the correct material
00979 
00980     cindices = this->selectionIndex.getValues(0);
00981     numcindices = this->selectionIndex.getNum();
00982 
00983     renderShape(static_cast<const SoGLCoordinateElement*>(coords), cindices, numcindices);
00984     state->pop();
00985 }
00986 
00987 void SoBrepPointSet::doAction(SoAction* action)
00988 {
00989     if (action->getTypeId() == Gui::SoHighlightElementAction::getClassTypeId()) {
00990         Gui::SoHighlightElementAction* hlaction = static_cast<Gui::SoHighlightElementAction*>(action);
00991         if (!hlaction->isHighlighted()) {
00992             this->highlightIndex = -1;
00993             return;
00994         }
00995         const SoPickedPoint* pp = hlaction->getElement();
00996         if (pp && pp->getDetail()) {
00997             const SoDetail* detail = pp->getDetail();
00998             if (!detail->isOfType(SoPointDetail::getClassTypeId())) {
00999                 this->highlightIndex = -1;
01000                 return;
01001             }
01002 
01003             int index = static_cast<const SoPointDetail*>(detail)->getCoordinateIndex();
01004             this->highlightIndex.setValue(index);
01005             this->highlightColor = hlaction->getColor();
01006         }
01007     }
01008     else if (action->getTypeId() == Gui::SoSelectionElementAction::getClassTypeId()) {
01009         Gui::SoSelectionElementAction* selaction = static_cast<Gui::SoSelectionElementAction*>(action);
01010         this->selectionColor = selaction->getColor();
01011         if (selaction->getType() == Gui::SoSelectionElementAction::All) {
01012             const SoCoordinateElement* coords = SoCoordinateElement::getInstance(action->getState());
01013             int num = coords->getNum() - this->startIndex.getValue();
01014             this->selectionIndex.setNum(num);
01015             int32_t* v = this->selectionIndex.startEditing();
01016             int32_t s = this->startIndex.getValue();
01017             for (int i=0; i<num;i++)
01018                 v[i] = i + s;
01019             this->selectionIndex.finishEditing();
01020             return;
01021         }
01022         else if (selaction->getType() == Gui::SoSelectionElementAction::None) {
01023             this->selectionIndex.setNum(0);
01024             return;
01025         }
01026 
01027         const SoPickedPoint* pp = selaction->getElement();
01028         if (pp && pp->getDetail()) {
01029             const SoDetail* detail = pp->getDetail();
01030             if (!detail->isOfType(SoPointDetail::getClassTypeId())) {
01031                 return;
01032             }
01033 
01034             int index = static_cast<const SoPointDetail*>(detail)->getCoordinateIndex();
01035             switch (selaction->getType()) {
01036             case Gui::SoSelectionElementAction::Append:
01037                 {
01038                     int start = this->selectionIndex.getNum();
01039                     this->selectionIndex.set1Value(start, index);
01040                 }
01041                 break;
01042             case Gui::SoSelectionElementAction::Remove:
01043                 {
01044                     int start = this->selectionIndex.find(index);
01045                     this->selectionIndex.deleteValues(start,1);
01046                 }
01047                 break;
01048             default:
01049                 break;
01050             }
01051         }
01052     }
01053 
01054     inherited::doAction(action);
01055 }

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