From d14d5cb2e44c6b89bc0e2f79af5d443922895059 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 15 Jun 2013 23:07:26 +0200 Subject: [PATCH] #0001093: Improvements for Brep Inventor nodes (disabled atm) --- src/Mod/Part/Gui/AppPartGui.cpp | 1 + src/Mod/Part/Gui/CMakeLists.txt | 2 + src/Mod/Part/Gui/SoBrepFaceSet.cpp | 987 +++++++++++++++++++++++++++ src/Mod/Part/Gui/SoBrepFaceSet.h | 128 ++++ src/Mod/Part/Gui/ViewProviderExt.cpp | 1 + 5 files changed, 1119 insertions(+) create mode 100644 src/Mod/Part/Gui/SoBrepFaceSet.cpp create mode 100644 src/Mod/Part/Gui/SoBrepFaceSet.h diff --git a/src/Mod/Part/Gui/AppPartGui.cpp b/src/Mod/Part/Gui/AppPartGui.cpp index 889e46fce..8a368bf64 100644 --- a/src/Mod/Part/Gui/AppPartGui.cpp +++ b/src/Mod/Part/Gui/AppPartGui.cpp @@ -25,6 +25,7 @@ #include #include "SoBrepShape.h" +#include "SoBrepFaceSet.h" #include "SoFCShapeObject.h" #include "ViewProvider.h" #include "ViewProviderExt.h" diff --git a/src/Mod/Part/Gui/CMakeLists.txt b/src/Mod/Part/Gui/CMakeLists.txt index 9d9d482eb..c2d457ba2 100644 --- a/src/Mod/Part/Gui/CMakeLists.txt +++ b/src/Mod/Part/Gui/CMakeLists.txt @@ -128,6 +128,8 @@ SET(PartGui_SRCS SoFCShapeObject.h SoBrepShape.cpp SoBrepShape.h + SoBrepFaceSet.cpp + SoBrepFaceSet.h ViewProvider.cpp ViewProvider.h ViewProviderExt.cpp diff --git a/src/Mod/Part/Gui/SoBrepFaceSet.cpp b/src/Mod/Part/Gui/SoBrepFaceSet.cpp new file mode 100644 index 000000000..7818e35ae --- /dev/null +++ b/src/Mod/Part/Gui/SoBrepFaceSet.cpp @@ -0,0 +1,987 @@ +/*************************************************************************** + * Copyright (c) 2011 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#if 0 +#ifndef _PreComp_ +# ifdef FC_OS_WIN32 +# include +# endif +# ifdef FC_OS_MACOSX +# include +# else +# include +# endif +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +#include +#include +#include + + +#include "SoBrepFaceSet.h" + + +using namespace PartGui; + + +SO_NODE_SOURCE(SoBrepFaceSet); + +void SoBrepFaceSet::initClass() +{ + SO_NODE_INIT_CLASS(SoBrepFaceSet, SoIndexedFaceSet, "IndexedFaceSet"); +} + +SoBrepFaceSet::SoBrepFaceSet() +{ + SO_NODE_CONSTRUCTOR(SoBrepFaceSet); + SO_NODE_ADD_FIELD(partIndex, (-1)); + SO_NODE_ADD_FIELD(highlightIndex, (-1)); + SO_NODE_ADD_FIELD(selectionIndex, (-1)); + selectionIndex.setNum(0); +} + + +SoBrepFaceSet::~SoBrepFaceSet() +{ +} + + +void SoBrepFaceSet::doAction(SoAction* action) +{ + if (action->getTypeId() == Gui::SoHighlightElementAction::getClassTypeId()) { + Gui::SoHighlightElementAction* hlaction = static_cast(action); + if (!hlaction->isHighlighted()) { + this->highlightIndex = -1; + return; + } + + const SoDetail* detail = hlaction->getElement(); + if (detail) { + if (detail->isOfType(SoFaceDetail::getClassTypeId())) { + int index = static_cast(detail)->getPartIndex(); + this->highlightIndex.setValue(index); + this->highlightColor = hlaction->getColor(); + } + else { + this->highlightIndex = -1; + return; + } + } + } + else if (action->getTypeId() == Gui::SoSelectionElementAction::getClassTypeId()) { + Gui::SoSelectionElementAction* selaction = static_cast(action); + this->selectionColor = selaction->getColor(); + if (selaction->getType() == Gui::SoSelectionElementAction::All) { + int num = this->partIndex.getNum(); + this->selectionIndex.setNum(num); + int32_t* v = this->selectionIndex.startEditing(); + for (int i=0; iselectionIndex.finishEditing(); + return; + } + else if (selaction->getType() == Gui::SoSelectionElementAction::None) { + this->selectionIndex.setNum(0); + return; + } + + const SoDetail* detail = selaction->getElement(); + if (detail) { + if (!detail->isOfType(SoFaceDetail::getClassTypeId())) { + return; + } + + int index = static_cast(detail)->getPartIndex(); + switch (selaction->getType()) { + case Gui::SoSelectionElementAction::Append: + { + int start = this->selectionIndex.getNum(); + this->selectionIndex.set1Value(start, index); + } + break; + case Gui::SoSelectionElementAction::Remove: + { + int start = this->selectionIndex.find(index); + this->selectionIndex.deleteValues(start,1); + } + break; + default: + break; + } + } + } + + inherited::doAction(action); +} + +void SoBrepFaceSet::GLRender(SoGLRenderAction *action) +{ + SoState * state = action->getState(); + + SoMaterialBundle mb(action); + Binding mbind = this->findMaterialBinding(state); + + SoTextureCoordinateBundle tb(action, TRUE, FALSE); + SbBool doTextures = tb.needCoordinates(); + + int32_t hl_idx = this->highlightIndex.getValue(); + int32_t num_selected = this->selectionIndex.getNum(); + + if (this->coordIndex.getNum() < 3) + return; + if (num_selected > 0) + renderSelection(action); + if (hl_idx >= 0) + renderHighlight(action); + + // When setting transparency shouldGLRender() handles the rendering and returns false. + // Therefore generatePrimitives() needs to be re-implemented to handle the materials + // correctly. + if (!this->shouldGLRender(action)) + return; + +#ifdef RENDER_GLARRAYS + if (!doTextures && index_array.size() && hl_idx < 0 && num_selected <= 0) { + if (mbind == 0) { + mb.sendFirst(); // only one material -> apply it! + renderSimpleArray(); + return; + } + else if (mbind == 1) { + renderColoredArray(&mb); + return; + } + } +#endif + + Binding nbind = this->findNormalBinding(state); + + const SoCoordinateElement * coords; + const SbVec3f * normals; + const int32_t * cindices; + int numindices; + const int32_t * nindices; + const int32_t * tindices; + const int32_t * mindices; + const int32_t * pindices; + int numparts; + SbBool normalCacheUsed; + + SbBool sendNormals = !mb.isColorOnly() || tb.isFunction(); + + this->getVertexData(state, coords, normals, cindices, + nindices, tindices, mindices, numindices, + sendNormals, normalCacheUsed); + + mb.sendFirst(); // make sure we have the correct material + + // just in case someone forgot + if (!mindices) mindices = cindices; + if (!nindices) nindices = cindices; + pindices = this->partIndex.getValues(0); + numparts = this->partIndex.getNum(); + + renderShape(static_cast(coords), cindices, numindices, + pindices, numparts, normals, nindices, &mb, mindices, &tb, tindices, nbind, mbind, doTextures?1:0); + + // Disable caching for this node + SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE); + + // Workaround for #0000433 +//#if !defined(FC_OS_WIN32) + if (hl_idx >= 0) + renderHighlight(action); + if (num_selected > 0) + renderSelection(action); +//#endif +} + +void SoBrepFaceSet::GLRenderBelowPath(SoGLRenderAction * action) +{ + inherited::GLRenderBelowPath(action); +} + + // this macro actually makes the code below more readable :-) +#define DO_VERTEX(idx) \ + if (mbind == PER_VERTEX) { \ + pointDetail.setMaterialIndex(matnr); \ + vertex.setMaterialIndex(matnr++); \ + } \ + else if (mbind == PER_VERTEX_INDEXED) { \ + pointDetail.setMaterialIndex(*mindices); \ + vertex.setMaterialIndex(*mindices++); \ + } \ + if (nbind == PER_VERTEX) { \ + pointDetail.setNormalIndex(normnr); \ + currnormal = &normals[normnr++]; \ + vertex.setNormal(*currnormal); \ + } \ + else if (nbind == PER_VERTEX_INDEXED) { \ + pointDetail.setNormalIndex(*nindices); \ + currnormal = &normals[*nindices++]; \ + vertex.setNormal(*currnormal); \ + } \ + if (tb.isFunction()) { \ + vertex.setTextureCoords(tb.get(coords->get3(idx), *currnormal)); \ + if (tb.needIndices()) pointDetail.setTextureCoordIndex(tindices ? *tindices++ : texidx++); \ + } \ + else if (tbind != NONE) { \ + pointDetail.setTextureCoordIndex(tindices ? *tindices : texidx); \ + vertex.setTextureCoords(tb.get(tindices ? *tindices++ : texidx++)); \ + } \ + vertex.setPoint(coords->get3(idx)); \ + pointDetail.setCoordinateIndex(idx); \ + this->shapeVertex(&vertex); + +void SoBrepFaceSet::generatePrimitives(SoAction * action) +{ + //TODO +#if 0 + inherited::generatePrimitives(action); +#else + //This is highly experimental!!! + + if (this->coordIndex.getNum() < 3) return; + + SoState * state = action->getState(); + + if (this->vertexProperty.getValue()) { + state->push(); + this->vertexProperty.getValue()->doAction(action); + } + + Binding mbind = this->findMaterialBinding(state); + Binding nbind = this->findNormalBinding(state); + + const SoCoordinateElement * coords; + const SbVec3f * normals; + const int32_t * cindices; + int numindices; + const int32_t * nindices; + const int32_t * tindices; + const int32_t * mindices; + SbBool doTextures; + SbBool sendNormals; + SbBool normalCacheUsed; + + sendNormals = TRUE; // always generate normals + + this->getVertexData(state, coords, normals, cindices, + nindices, tindices, mindices, numindices, + sendNormals, normalCacheUsed); + + SoTextureCoordinateBundle tb(action, FALSE, FALSE); + doTextures = tb.needCoordinates(); + + if (!sendNormals) nbind = OVERALL; + else if (normalCacheUsed && nbind == PER_VERTEX) { + nbind = PER_VERTEX_INDEXED; + } + else if (normalCacheUsed && nbind == PER_FACE_INDEXED) { + nbind = PER_FACE; + } + + if (this->getNodeType() == SoNode::VRML1) { + // For VRML1, PER_VERTEX means per vertex in shape, not PER_VERTEX + // on the state. + if (mbind == PER_VERTEX) { + mbind = PER_VERTEX_INDEXED; + mindices = cindices; + } + if (nbind == PER_VERTEX) { + nbind = PER_VERTEX_INDEXED; + nindices = cindices; + } + } + + Binding tbind = NONE; + if (doTextures) { + if (tb.isFunction() && !tb.needIndices()) { + tbind = NONE; + tindices = NULL; + } + // FIXME: just call inherited::areTexCoordsIndexed() instead of + // the if-check? 20020110 mortene. + else if (SoTextureCoordinateBindingElement::get(state) == + SoTextureCoordinateBindingElement::PER_VERTEX) { + tbind = PER_VERTEX; + tindices = NULL; + } + else { + tbind = PER_VERTEX_INDEXED; + if (tindices == NULL) tindices = cindices; + } + } + + if (nbind == PER_VERTEX_INDEXED && nindices == NULL) { + nindices = cindices; + } + if (mbind == PER_VERTEX_INDEXED && mindices == NULL) { + mindices = cindices; + } + + int texidx = 0; + TriangleShape mode = POLYGON; + TriangleShape newmode; + const int32_t *viptr = cindices; + const int32_t *viendptr = viptr + numindices; + const int32_t *piptr = this->partIndex.getValues(0); + int num_partindices = this->partIndex.getNum(); + const int32_t *piendptr = piptr + num_partindices; + int32_t v1, v2, v3, v4, v5 = 0, pi; // v5 init unnecessary, but kills a compiler warning. + + SoPrimitiveVertex vertex; + SoPointDetail pointDetail; + SoFaceDetail faceDetail; + + vertex.setDetail(&pointDetail); + + SbVec3f dummynormal(0,0,1); + const SbVec3f *currnormal = &dummynormal; + if (normals) currnormal = normals; + vertex.setNormal(*currnormal); + + int matnr = 0; + int normnr = 0; + int trinr = 0; + pi = piptr < piendptr ? *piptr++ : -1; + while (pi == 0) { + // It may happen that a part has no triangles + pi = piptr < piendptr ? *piptr++ : -1; + if (mbind == PER_PART) + matnr++; + else if (mbind == PER_PART_INDEXED) + mindices++; + } + + while (viptr + 2 < viendptr) { + v1 = *viptr++; + v2 = *viptr++; + v3 = *viptr++; + if (v1 < 0 || v2 < 0 || v3 < 0) { + break; + } + v4 = viptr < viendptr ? *viptr++ : -1; + if (v4 < 0) newmode = TRIANGLES; + else { + v5 = viptr < viendptr ? *viptr++ : -1; + if (v5 < 0) newmode = QUADS; + else newmode = POLYGON; + } + if (newmode != mode) { + if (mode != POLYGON) this->endShape(); + mode = newmode; + this->beginShape(action, mode, &faceDetail); + } + else if (mode == POLYGON) this->beginShape(action, POLYGON, &faceDetail); + + // vertex 1 can't use DO_VERTEX + if (mbind == PER_PART) { + if (trinr == 0) { + pointDetail.setMaterialIndex(matnr); + vertex.setMaterialIndex(matnr++); + } + } + else if (mbind == PER_PART_INDEXED) { + if (trinr == 0) { + pointDetail.setMaterialIndex(*mindices); + vertex.setMaterialIndex(*mindices++); + } + } + else if (mbind == PER_VERTEX || mbind == PER_FACE) { + pointDetail.setMaterialIndex(matnr); + vertex.setMaterialIndex(matnr++); + } + else if (mbind == PER_VERTEX_INDEXED || mbind == PER_FACE_INDEXED) { + pointDetail.setMaterialIndex(*mindices); + vertex.setMaterialIndex(*mindices++); + } + if (nbind == PER_VERTEX || nbind == PER_FACE) { + pointDetail.setNormalIndex(normnr); + currnormal = &normals[normnr++]; + vertex.setNormal(*currnormal); + } + else if (nbind == PER_FACE_INDEXED || nbind == PER_VERTEX_INDEXED) { + pointDetail.setNormalIndex(*nindices); + currnormal = &normals[*nindices++]; + vertex.setNormal(*currnormal); + } + + if (tb.isFunction()) { + vertex.setTextureCoords(tb.get(coords->get3(v1), *currnormal)); + if (tb.needIndices()) pointDetail.setTextureCoordIndex(tindices ? *tindices++ : texidx++); + } + else if (tbind != NONE) { + pointDetail.setTextureCoordIndex(tindices ? *tindices : texidx); + vertex.setTextureCoords(tb.get(tindices ? *tindices++ : texidx++)); + } + pointDetail.setCoordinateIndex(v1); + vertex.setPoint(coords->get3(v1)); + this->shapeVertex(&vertex); + + DO_VERTEX(v2); + DO_VERTEX(v3); + + if (mode != TRIANGLES) { + DO_VERTEX(v4); + if (mode == POLYGON) { + DO_VERTEX(v5); + v1 = viptr < viendptr ? *viptr++ : -1; + while (v1 >= 0) { + DO_VERTEX(v1); + v1 = viptr < viendptr ? *viptr++ : -1; + } + this->endShape(); + } + } + faceDetail.incFaceIndex(); + if (mbind == PER_VERTEX_INDEXED) { + mindices++; + } + if (nbind == PER_VERTEX_INDEXED) { + nindices++; + } + if (tindices) tindices++; + + trinr++; + if (pi == trinr) { + pi = piptr < piendptr ? *piptr++ : -1; + while (pi == 0) { + // It may happen that a part has no triangles + pi = piptr < piendptr ? *piptr++ : -1; + if (mbind == PER_PART) + matnr++; + else if (mbind == PER_PART_INDEXED) + mindices++; + } + trinr = 0; + } + } + if (mode != POLYGON) this->endShape(); + + if (normalCacheUsed) { + this->readUnlockNormalCache(); + } + + if (this->vertexProperty.getValue()) { + state->pop(); + } +#endif +} + +#undef DO_VERTEX + +void SoBrepFaceSet::renderHighlight(SoGLRenderAction *action) +{ + SoState * state = action->getState(); + state->push(); + + SoLazyElement::setEmissive(state, &this->highlightColor); + SoOverrideElement::setEmissiveColorOverride(state, this, TRUE); +#if 0 // disables shading effect + // sendNormals will be FALSE + SoLazyElement::setDiffuse(state, this,1, &this->highlightColor,&this->colorpacker); + SoOverrideElement::setDiffuseColorOverride(state, this, TRUE); + SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR); +#endif + + Binding mbind = this->findMaterialBinding(state); + Binding nbind = this->findNormalBinding(state); + + const SoCoordinateElement * coords; + const SbVec3f * normals; + const int32_t * cindices; + int numindices; + const int32_t * nindices; + const int32_t * tindices; + const int32_t * mindices; + const int32_t * pindices; + SbBool doTextures; + SbBool normalCacheUsed; + + SoMaterialBundle mb(action); + SoTextureCoordinateBundle tb(action, TRUE, FALSE); + doTextures = tb.needCoordinates(); + SbBool sendNormals = !mb.isColorOnly() || tb.isFunction(); + + this->getVertexData(state, coords, normals, cindices, + nindices, tindices, mindices, numindices, + sendNormals, normalCacheUsed); + + mb.sendFirst(); // make sure we have the correct material + + int32_t id = this->highlightIndex.getValue(); + + // just in case someone forgot + if (!mindices) mindices = cindices; + if (!nindices) nindices = cindices; + pindices = this->partIndex.getValues(0); + + // coords + int length = (int)pindices[id]*4; + int start=0; + for (int i=0;i(coords), &(cindices[start]), length, + &(pindices[id]), 1, normals, nindices, &mb, mindices, &tb, tindices, nbind, mbind, doTextures?1:0); + state->pop(); +} + +void SoBrepFaceSet::renderSelection(SoGLRenderAction *action) +{ + int numSelected = this->selectionIndex.getNum(); + const int32_t* selected = this->selectionIndex.getValues(0); + if (numSelected == 0) return; + + SoState * state = action->getState(); + state->push(); + + SoLazyElement::setEmissive(state, &this->selectionColor); + SoOverrideElement::setEmissiveColorOverride(state, this, TRUE); +#if 0 // disables shading effect + SoLazyElement::setDiffuse(state, this,1, &this->selectionColor,&this->colorpacker); + SoOverrideElement::setDiffuseColorOverride(state, this, TRUE); + SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR); +#endif + + Binding mbind = this->findMaterialBinding(state); + Binding nbind = this->findNormalBinding(state); + + const SoCoordinateElement * coords; + const SbVec3f * normals; + const int32_t * cindices; + int numindices; + const int32_t * nindices; + const int32_t * tindices; + const int32_t * mindices; + const int32_t * pindices; + SbBool doTextures; + SbBool normalCacheUsed; + + SoMaterialBundle mb(action); + SoTextureCoordinateBundle tb(action, TRUE, FALSE); + doTextures = tb.needCoordinates(); + SbBool sendNormals = !mb.isColorOnly() || tb.isFunction(); + + this->getVertexData(state, coords, normals, cindices, + nindices, tindices, mindices, numindices, + sendNormals, normalCacheUsed); + + mb.sendFirst(); // make sure we have the correct material + + // just in case someone forgot + if (!mindices) mindices = cindices; + if (!nindices) nindices = cindices; + pindices = this->partIndex.getValues(0); + + // materials + mbind = OVERALL; + doTextures = FALSE; + + for (int i=0; i(coords), &(cindices[start]), length, + &(pindices[id]), 1, normals_s, nindices_s, &mb, mindices, &tb, tindices, nbind, mbind, doTextures?1:0); + } + state->pop(); +} + + +SoDetail * SoBrepFaceSet::createTriangleDetail(SoRayPickAction * action, + const SoPrimitiveVertex * v1, + const SoPrimitiveVertex * v2, + const SoPrimitiveVertex * v3, + SoPickedPoint * pp) +{ + SoDetail* detail = inherited::createTriangleDetail(action, v1, v2, v3, pp); + const int32_t * indices = this->partIndex.getValues(0); + int num = this->partIndex.getNum(); + if (indices) { + SoFaceDetail* face_detail = static_cast(detail); + int index = face_detail->getFaceIndex(); + int count = 0; + for (int i=0; isetPartIndex(i); + break; + } + } + } + return detail; +} + +SoBrepFaceSet::Binding +SoBrepFaceSet::findMaterialBinding(SoState * const state) const +{ + Binding binding = OVERALL; + SoMaterialBindingElement::Binding matbind = + SoMaterialBindingElement::get(state); + + switch (matbind) { + case SoMaterialBindingElement::OVERALL: + binding = OVERALL; + break; + case SoMaterialBindingElement::PER_VERTEX: + binding = PER_VERTEX; + break; + case SoMaterialBindingElement::PER_VERTEX_INDEXED: + binding = PER_VERTEX_INDEXED; + break; + case SoMaterialBindingElement::PER_PART: + binding = PER_PART; + break; + case SoMaterialBindingElement::PER_FACE: + binding = PER_FACE; + break; + case SoMaterialBindingElement::PER_PART_INDEXED: + binding = PER_PART_INDEXED; + break; + case SoMaterialBindingElement::PER_FACE_INDEXED: + binding = PER_FACE_INDEXED; + break; + default: + break; + } + return binding; +} + +SoBrepFaceSet::Binding +SoBrepFaceSet::findNormalBinding(SoState * const state) const +{ + Binding binding = PER_VERTEX_INDEXED; + SoNormalBindingElement::Binding normbind = + (SoNormalBindingElement::Binding) SoNormalBindingElement::get(state); + + switch (normbind) { + case SoNormalBindingElement::OVERALL: + binding = OVERALL; + break; + case SoNormalBindingElement::PER_VERTEX: + binding = PER_VERTEX; + break; + case SoNormalBindingElement::PER_VERTEX_INDEXED: + binding = PER_VERTEX_INDEXED; + break; + case SoNormalBindingElement::PER_PART: + binding = PER_PART; + break; + case SoNormalBindingElement::PER_FACE: + binding = PER_FACE; + break; + case SoNormalBindingElement::PER_PART_INDEXED: + binding = PER_PART_INDEXED; + break; + case SoNormalBindingElement::PER_FACE_INDEXED: + binding = PER_FACE_INDEXED; + break; + default: + break; + } + return binding; +} + + +//**************************************************************************** +// renderShape: fallback rendering: one vertex at a time +// +void SoBrepFaceSet::renderShape(const SoGLCoordinateElement * const vertexlist, + const int32_t *vertexindices, + int num_indices, + const int32_t *partindices, + int num_partindices, + const SbVec3f *normals, + const int32_t *normalindices, + SoMaterialBundle *const materials, + const int32_t *matindices, + SoTextureCoordinateBundle * const texcoords, + const int32_t *texindices, + const int nbind, + const int mbind, + const int texture) +{ + int texidx = 0; + + const SbVec3f * coords3d = NULL; + coords3d = vertexlist->getArrayPtr3(); + + const int32_t *viptr = vertexindices; + const int32_t *viendptr = viptr + num_indices; + const int32_t *piptr = partindices; + const int32_t *piendptr = piptr + num_partindices; + int32_t v1, v2, v3, v4, pi; + SbVec3f dummynormal(0,0,1); + int numverts = vertexlist->getNum(); + + const SbVec3f *currnormal = &dummynormal; + if (normals) currnormal = normals; + + int matnr = 0; + int trinr = 0; + pi = piptr < piendptr ? *piptr++ : -1; + while (pi == 0) { + // It may happen that a part has no triangles + pi = piptr < piendptr ? *piptr++ : -1; + if (mbind == PER_PART) + matnr++; + else if (mbind == PER_PART_INDEXED) + matindices++; + } + + glBegin(GL_TRIANGLES); + while (viptr + 2 < viendptr) { + v1 = *viptr++; + v2 = *viptr++; + v3 = *viptr++; + + // This test is for robustness upon buggy data sets + if (v1 < 0 || v2 < 0 || v3 < 0 || + v1 >= numverts || v2 >= numverts || v3 >= numverts) { + break; + } + v4 = viptr < viendptr ? *viptr++ : -1; + + /* vertex 1 *********************************************************/ + if (mbind == PER_PART) { + if (trinr == 0) + materials->send(matnr++, TRUE); + } + else if (mbind == PER_PART_INDEXED) { + if (trinr == 0) + materials->send(*matindices++, TRUE); + } + else if (mbind == PER_VERTEX || mbind == PER_FACE) { + materials->send(matnr++, TRUE); + } + else if (mbind == PER_VERTEX_INDEXED || mbind == PER_FACE_INDEXED) { + materials->send(*matindices++, TRUE); + } + + if (normals) { + if (nbind == PER_VERTEX || nbind == PER_FACE) { + currnormal = normals++; + glNormal3fv((const GLfloat*)currnormal); + } + else if (nbind == PER_VERTEX_INDEXED || nbind == PER_FACE_INDEXED) { + currnormal = &normals[*normalindices++]; + glNormal3fv((const GLfloat*)currnormal); + } + } + + if (texture) { + texcoords->send(texindices ? *texindices++ : texidx++, + vertexlist->get3(v1), + *currnormal); + } + + glVertex3fv((const GLfloat*) (coords3d + v1)); + + /* vertex 2 *********************************************************/ + if (mbind == PER_VERTEX) + materials->send(matnr++, TRUE); + else if (mbind == PER_VERTEX_INDEXED) + materials->send(*matindices++, TRUE); + + if (normals) { + if (nbind == PER_VERTEX) { + currnormal = normals++; + glNormal3fv((const GLfloat*)currnormal); + } + else if (nbind == PER_VERTEX_INDEXED) { + currnormal = &normals[*normalindices++]; + glNormal3fv((const GLfloat*)currnormal); + } + } + + if (texture) { + texcoords->send(texindices ? *texindices++ : texidx++, + vertexlist->get3(v2), + *currnormal); + } + + glVertex3fv((const GLfloat*) (coords3d + v2)); + + /* vertex 3 *********************************************************/ + if (mbind == PER_VERTEX) + materials->send(matnr++, TRUE); + else if (mbind == PER_VERTEX_INDEXED) + materials->send(*matindices++, TRUE); + + if (normals) { + if (nbind == PER_VERTEX) { + currnormal = normals++; + glNormal3fv((const GLfloat*)currnormal); + } + else if (nbind == PER_VERTEX_INDEXED) { + currnormal = &normals[*normalindices++]; + glNormal3fv((const GLfloat*)currnormal); + } + } + + if (texture) { + texcoords->send(texindices ? *texindices++ : texidx++, + vertexlist->get3(v3), + *currnormal); + } + + glVertex3fv((const GLfloat*) (coords3d + v3)); + + if (mbind == PER_VERTEX_INDEXED) + matindices++; + + if (nbind == PER_VERTEX_INDEXED) + normalindices++; + + if (texture && texindices) { + texindices++; + } + + trinr++; + if (pi == trinr) { + pi = piptr < piendptr ? *piptr++ : -1; + while (pi == 0) { + // It may happen that a part has no triangles + pi = piptr < piendptr ? *piptr++ : -1; + if (mbind == PER_PART) + matnr++; + else if (mbind == PER_PART_INDEXED) + matindices++; + } + trinr = 0; + } + } + glEnd(); +} + + +#ifdef RENDER_GLARRAYS +//**************************************************************************** +// renderSimpleArray: normal and coord from vertex_array; +// no texture, color, highlight or selection but highet possible speed; +// all vertices written in one go! +// +void SoBrepFaceSet::renderSimpleArray() +{ + int cnt = index_array.size(); + + glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + + glInterleavedArrays(GL_N3F_V3F, 0, vertex_array.data()); + glDrawElements(GL_TRIANGLES, cnt, GL_UNSIGNED_INT, index_array.data()); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); +} +#endif + + +#ifdef RENDER_GLARRAYS +//**************************************************************************** +// renderColoredArray: normal and coord from vertex_array; +// no texture, highlight or selection but color / material array. +// needs to iterate over parts (i.e. geometry faces) +// +void SoBrepFaceSet::renderColoredArray(SoMaterialBundle *const materials) +{ + int num_parts = partIndex.getNum(); + int cnt = index_array.size(); + + glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + + glInterleavedArrays(GL_N3F_V3F, 0, vertex_array.data()); + const int32_t* ptr = index_array.data(); + + for (int part_id = 0; part_id < num_parts; part_id++) { + int tris = partIndex[part_id]; + + if (tris > 0) { + materials->send(part_id, TRUE); + glDrawElements(GL_TRIANGLES, 3 * tris, GL_UNSIGNED_INT, ptr); + ptr += 3 * tris; + } + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); +} +#endif + +#endif + diff --git a/src/Mod/Part/Gui/SoBrepFaceSet.h b/src/Mod/Part/Gui/SoBrepFaceSet.h new file mode 100644 index 000000000..9259601a0 --- /dev/null +++ b/src/Mod/Part/Gui/SoBrepFaceSet.h @@ -0,0 +1,128 @@ +/*************************************************************************** + * Copyright (c) 2011 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef PARTGUI_SOBREPFACESET_H +#define PARTGUI_SOBREPFACESET_H +#if 0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class SoGLCoordinateElement; +class SoTextureCoordinateBundle; + + +#define RENDER_GLARRAYS + +namespace PartGui { + +class VertexArray; + + +class PartGuiExport SoBrepFaceSet : public SoIndexedFaceSet { + typedef SoIndexedFaceSet inherited; + + SO_NODE_HEADER(SoBrepFaceSet); + +public: + static void initClass(); + SoBrepFaceSet(); + + SoMFInt32 partIndex; + SoSFInt32 highlightIndex; + SoMFInt32 selectionIndex; + +#ifdef RENDER_GLARRAYS + std::vector index_array; + std::vector vertex_array; +#endif + + enum Binding { + OVERALL = 0, + PER_PART, + PER_PART_INDEXED, + PER_FACE, + PER_FACE_INDEXED, + PER_VERTEX, + PER_VERTEX_INDEXED, + NONE = OVERALL + }; + +protected: + virtual ~SoBrepFaceSet(); + virtual void GLRender(SoGLRenderAction *action); + virtual void GLRenderBelowPath(SoGLRenderAction * action); + virtual void doAction(SoAction* action); + virtual SoDetail * createTriangleDetail( + SoRayPickAction * action, + const SoPrimitiveVertex * v1, + const SoPrimitiveVertex * v2, + const SoPrimitiveVertex * v3, + SoPickedPoint * pp); + virtual void generatePrimitives(SoAction * action); + +private: + Binding findMaterialBinding(SoState * const state) const; + Binding findNormalBinding(SoState * const state) const; + void renderHighlight(SoGLRenderAction *action); + void renderSelection(SoGLRenderAction *action); + + + // low-level render functions + + void renderShape(const SoGLCoordinateElement * const vertexlist, + const int32_t *vertexindices, + int num_vertexindices, + const int32_t *partindices, + int num_partindices, + const SbVec3f *normals, + const int32_t *normindices, + SoMaterialBundle *const materials, + const int32_t *matindices, + SoTextureCoordinateBundle * const texcoords, + const int32_t *texindices, + const int nbind, + const int mbind, + const int texture); + +#ifdef RENDER_GLARRAYS + void renderSimpleArray(); + void renderColoredArray(SoMaterialBundle *const materials); +#endif + +private: + SbColor selectionColor; + SbColor highlightColor; + SoColorPacker colorpacker; +}; + +} // namespace PartGui +#endif +#endif // PARTGUI_SOBREPFACESET_H + diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index 7dc155b08..cf35e4a14 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -102,6 +102,7 @@ #include "ViewProviderExt.h" #include "SoBrepShape.h" +#include "SoBrepFaceSet.h" #include "TaskFaceColors.h" #include