diff --git a/src/Mod/Part/Gui/AppPartGui.cpp b/src/Mod/Part/Gui/AppPartGui.cpp index 10f5c40f6..83dc2c1ea 100644 --- a/src/Mod/Part/Gui/AppPartGui.cpp +++ b/src/Mod/Part/Gui/AppPartGui.cpp @@ -24,8 +24,9 @@ #include -#include "SoBrepShape.h" #include "SoBrepFaceSet.h" +#include "SoBrepEdgeSet.h" +#include "SoBrepPointSet.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 16d24db68..fd6f6b465 100644 --- a/src/Mod/Part/Gui/CMakeLists.txt +++ b/src/Mod/Part/Gui/CMakeLists.txt @@ -131,10 +131,12 @@ SET(PartGui_SRCS PreCompiled.h SoFCShapeObject.cpp SoFCShapeObject.h - SoBrepShape.cpp - SoBrepShape.h + SoBrepEdgeSet.cpp + SoBrepEdgeSet.h SoBrepFaceSet.cpp SoBrepFaceSet.h + SoBrepPointSet.cpp + SoBrepPointSet.h ViewProvider.cpp ViewProvider.h ViewProviderExt.cpp diff --git a/src/Mod/Part/Gui/DlgFilletEdges.cpp b/src/Mod/Part/Gui/DlgFilletEdges.cpp index f6ea3929f..07e269a43 100644 --- a/src/Mod/Part/Gui/DlgFilletEdges.cpp +++ b/src/Mod/Part/Gui/DlgFilletEdges.cpp @@ -49,7 +49,10 @@ #include "DlgFilletEdges.h" #include "ui_DlgFilletEdges.h" -#include "SoBrepShape.h" +#include "SoBrepFaceSet.h" +#include "SoBrepEdgeSet.h" +#include "SoBrepPointSet.h" + #include "../App/PartFeature.h" #include "../App/FeatureFillet.h" diff --git a/src/Mod/Part/Gui/SoBrepEdgeSet.cpp b/src/Mod/Part/Gui/SoBrepEdgeSet.cpp new file mode 100644 index 000000000..ae725e86e --- /dev/null +++ b/src/Mod/Part/Gui/SoBrepEdgeSet.cpp @@ -0,0 +1,328 @@ +/*************************************************************************** + * 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" + +#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 "SoBrepEdgeSet.h" +#include +#include + +using namespace PartGui; + + +SO_NODE_SOURCE(SoBrepEdgeSet); + +void SoBrepEdgeSet::initClass() +{ + SO_NODE_INIT_CLASS(SoBrepEdgeSet, SoIndexedLineSet, "IndexedLineSet"); +} + +SoBrepEdgeSet::SoBrepEdgeSet() +{ + SO_NODE_CONSTRUCTOR(SoBrepEdgeSet); + SO_NODE_ADD_FIELD(highlightIndex, (-1)); + SO_NODE_ADD_FIELD(selectionIndex, (-1)); + selectionIndex.setNum(0); +} + +void SoBrepEdgeSet::GLRender(SoGLRenderAction *action) +{ + if (this->selectionIndex.getNum() > 0) + renderSelection(action); + if (this->highlightIndex.getValue() >= 0) + renderHighlight(action); + inherited::GLRender(action); + + // Workaround for #0000433 +//#if !defined(FC_OS_WIN32) + if (this->highlightIndex.getValue() >= 0) + renderHighlight(action); + if (this->selectionIndex.getNum() > 0) + renderSelection(action); +//#endif +} + +void SoBrepEdgeSet::GLRenderBelowPath(SoGLRenderAction * action) +{ + inherited::GLRenderBelowPath(action); +} + +void SoBrepEdgeSet::renderShape(const SoGLCoordinateElement * const coords, + const int32_t *cindices, int numindices) +{ + + const SbVec3f * coords3d = coords->getArrayPtr3(); + + int32_t i; + int previ; + const int32_t *end = cindices + numindices; + while (cindices < end) { + glBegin(GL_LINE_STRIP); + previ = *cindices++; + i = (cindices < end) ? *cindices++ : -1; + while (i >= 0) { + glVertex3fv((const GLfloat*) (coords3d + previ)); + glVertex3fv((const GLfloat*) (coords3d + i)); + previ = i; + i = cindices < end ? *cindices++ : -1; + } + glEnd(); + } +} + +void SoBrepEdgeSet::renderHighlight(SoGLRenderAction *action) +{ + SoState * state = action->getState(); + state->push(); + //SoLineWidthElement::set(state, this, 4.0f); + + SoLazyElement::setEmissive(state, &this->highlightColor); + SoOverrideElement::setEmissiveColorOverride(state, this, TRUE); + SoLazyElement::setDiffuse(state, this,1, &this->highlightColor,&this->colorpacker1); + SoOverrideElement::setDiffuseColorOverride(state, this, TRUE); + SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR); + + const SoCoordinateElement * coords; + const SbVec3f * normals; + const int32_t * cindices; + int numcindices; + const int32_t * nindices; + const int32_t * tindices; + const int32_t * mindices; + SbBool normalCacheUsed; + + this->getVertexData(state, coords, normals, cindices, nindices, + tindices, mindices, numcindices, FALSE, normalCacheUsed); + + SoMaterialBundle mb(action); + mb.sendFirst(); // make sure we have the correct material + + const int32_t* id = &(this->hl[0]); + int num = (int)this->hl.size(); + + renderShape(static_cast(coords), id, num); + state->pop(); +} + +void SoBrepEdgeSet::renderSelection(SoGLRenderAction *action) +{ + int numSelected = this->selectionIndex.getNum(); + if (numSelected == 0) return; + + SoState * state = action->getState(); + state->push(); + //SoLineWidthElement::set(state, this, 4.0f); + + SoLazyElement::setEmissive(state, &this->selectionColor); + SoOverrideElement::setEmissiveColorOverride(state, this, TRUE); + SoLazyElement::setDiffuse(state, this,1, &this->selectionColor,&this->colorpacker2); + SoOverrideElement::setDiffuseColorOverride(state, this, TRUE); + SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR); + + const SoCoordinateElement * coords; + const SbVec3f * normals; + const int32_t * cindices; + int numcindices; + const int32_t * nindices; + const int32_t * tindices; + const int32_t * mindices; + SbBool normalCacheUsed; + + this->getVertexData(state, coords, normals, cindices, nindices, + tindices, mindices, numcindices, FALSE, normalCacheUsed); + + SoMaterialBundle mb(action); + mb.sendFirst(); // make sure we have the correct material + + cindices = &(this->sl[0]); + numcindices = (int)this->sl.size(); + + renderShape(static_cast(coords), cindices, numcindices); + state->pop(); +} + +static void createIndexArray(const int32_t* segm, int numsegm, + const int32_t* cindices, int numcindices, + std::vector& out) +{ + std::vector v; + for (int j=0; j index) + break; + if (cindices[i] < 0) + section++; + } + + v.insert(v.end(), cindices+start, cindices+start+num); + } + + out.swap(v); +} + +void SoBrepEdgeSet::doAction(SoAction* action) +{ + if (action->getTypeId() == Gui::SoHighlightElementAction::getClassTypeId()) { + Gui::SoHighlightElementAction* hlaction = static_cast(action); + if (!hlaction->isHighlighted()) { + this->highlightIndex = -1; + this->hl.clear(); + return; + } + const SoDetail* detail = hlaction->getElement(); + if (detail) { + if (!detail->isOfType(SoLineDetail::getClassTypeId())) { + this->highlightIndex = -1; + this->hl.clear(); + return; + } + + this->highlightColor = hlaction->getColor(); + int32_t index = static_cast(detail)->getLineIndex(); + const int32_t* cindices = this->coordIndex.getValues(0); + int numcindices = this->coordIndex.getNum(); + + createIndexArray(&index, 1, cindices, numcindices, this->hl); + this->highlightIndex.setValue(index); + } + } + else if (action->getTypeId() == Gui::SoSelectionElementAction::getClassTypeId()) { + Gui::SoSelectionElementAction* selaction = static_cast(action); + + this->selectionColor = selaction->getColor(); + if (selaction->getType() == Gui::SoSelectionElementAction::All) { + const int32_t* cindices = this->coordIndex.getValues(0); + int numcindices = this->coordIndex.getNum(); + unsigned int num = std::count_if(cindices, cindices+numcindices, + std::bind2nd(std::equal_to(), -1)); + + this->sl.clear(); + this->selectionIndex.setNum(num); + int32_t* v = this->selectionIndex.startEditing(); + for (unsigned int i=0; iselectionIndex.finishEditing(); + + int numsegm = this->selectionIndex.getNum(); + if (numsegm > 0) { + const int32_t* selsegm = this->selectionIndex.getValues(0); + const int32_t* cindices = this->coordIndex.getValues(0); + int numcindices = this->coordIndex.getNum(); + createIndexArray(selsegm, numsegm, cindices, numcindices, this->sl); + } + return; + } + else if (selaction->getType() == Gui::SoSelectionElementAction::None) { + this->selectionIndex.setNum(0); + this->sl.clear(); + return; + } + + const SoDetail* detail = selaction->getElement(); + if (detail) { + if (!detail->isOfType(SoLineDetail::getClassTypeId())) { + return; + } + + int index = static_cast(detail)->getLineIndex(); + 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; + } + + int numsegm = this->selectionIndex.getNum(); + if (numsegm > 0) { + const int32_t* selsegm = this->selectionIndex.getValues(0); + const int32_t* cindices = this->coordIndex.getValues(0); + int numcindices = this->coordIndex.getNum(); + createIndexArray(selsegm, numsegm, cindices, numcindices, this->sl); + } + } + } + + inherited::doAction(action); +} + +SoDetail * SoBrepEdgeSet::createLineSegmentDetail(SoRayPickAction * action, + const SoPrimitiveVertex * v1, + const SoPrimitiveVertex * v2, + SoPickedPoint * pp) +{ + SoDetail* detail = inherited::createLineSegmentDetail(action, v1, v2, pp); + SoLineDetail* line_detail = static_cast(detail); + int index = line_detail->getLineIndex(); + line_detail->setPartIndex(index); + return detail; +} diff --git a/src/Mod/Part/Gui/SoBrepEdgeSet.h b/src/Mod/Part/Gui/SoBrepEdgeSet.h new file mode 100644 index 000000000..554b0f922 --- /dev/null +++ b/src/Mod/Part/Gui/SoBrepEdgeSet.h @@ -0,0 +1,84 @@ +/*************************************************************************** + * 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_SOBREPEDGESET_H +#define PARTGUI_SOBREPEDGESET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class SoGLCoordinateElement; +class SoTextureCoordinateBundle; + +namespace PartGui { + +class PartGuiExport SoBrepEdgeSet : public SoIndexedLineSet { + typedef SoIndexedLineSet inherited; + + SO_NODE_HEADER(SoBrepEdgeSet); + +public: + static void initClass(); + SoBrepEdgeSet(); + + SoSFInt32 highlightIndex; + SoMFInt32 selectionIndex; + +protected: + virtual ~SoBrepEdgeSet() {}; + virtual void GLRender(SoGLRenderAction *action); + virtual void GLRenderBelowPath(SoGLRenderAction * action); + virtual void doAction(SoAction* action); + virtual SoDetail * createLineSegmentDetail( + SoRayPickAction *action, + const SoPrimitiveVertex *v1, + const SoPrimitiveVertex *v2, + SoPickedPoint *pp); +private: + void renderShape(const SoGLCoordinateElement * const vertexlist, + const int32_t *vertexindices, + int num_vertexindices); + void renderHighlight(SoGLRenderAction *action); + void renderSelection(SoGLRenderAction *action); + +private: + std::vector hl, sl; + SbColor selectionColor; + SbColor highlightColor; + //#0000834: Minor preselection color bug + //To solve this we need a seprate color packer for highlighting and selection + SoColorPacker colorpacker1; + SoColorPacker colorpacker2; +}; + +} // namespace PartGui + + +#endif // PARTGUI_SOBREPEDGESET_H + diff --git a/src/Mod/Part/Gui/SoBrepFaceSet.cpp b/src/Mod/Part/Gui/SoBrepFaceSet.cpp index 7818e35ae..2005343de 100644 --- a/src/Mod/Part/Gui/SoBrepFaceSet.cpp +++ b/src/Mod/Part/Gui/SoBrepFaceSet.cpp @@ -22,7 +22,7 @@ #include "PreCompiled.h" -#if 0 + #ifndef _PreComp_ # ifdef FC_OS_WIN32 # include @@ -56,12 +56,9 @@ # include #endif +#include "SoBrepFaceSet.h" #include #include -#include - - -#include "SoBrepFaceSet.h" using namespace PartGui; @@ -83,12 +80,10 @@ SoBrepFaceSet::SoBrepFaceSet() selectionIndex.setNum(0); } - SoBrepFaceSet::~SoBrepFaceSet() { } - void SoBrepFaceSet::doAction(SoAction* action) { if (action->getTypeId() == Gui::SoHighlightElementAction::getClassTypeId()) { @@ -157,6 +152,7 @@ void SoBrepFaceSet::doAction(SoAction* action) inherited::doAction(action); } +#ifdef RENDER_GLARRAYS void SoBrepFaceSet::GLRender(SoGLRenderAction *action) { SoState * state = action->getState(); @@ -167,8 +163,8 @@ void SoBrepFaceSet::GLRender(SoGLRenderAction *action) SoTextureCoordinateBundle tb(action, TRUE, FALSE); SbBool doTextures = tb.needCoordinates(); - int32_t hl_idx = this->highlightIndex.getValue(); - int32_t num_selected = this->selectionIndex.getNum(); + int32_t hl_idx = this->highlightIndex.getValue(); + int32_t num_selected = this->selectionIndex.getNum(); if (this->coordIndex.getNum() < 3) return; @@ -184,17 +180,17 @@ void SoBrepFaceSet::GLRender(SoGLRenderAction *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; - } - } + 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); @@ -239,6 +235,130 @@ void SoBrepFaceSet::GLRender(SoGLRenderAction *action) //#endif } +//**************************************************************************** +// 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(); + if (cnt == 0) return; + + glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + +#if 0 + glInterleavedArrays(GL_N3F_V3F, 0, vertex_array.data()); + glDrawElements(GL_TRIANGLES, cnt, GL_UNSIGNED_INT, index_array.data()); +#else + glInterleavedArrays(GL_N3F_V3F, 0, &(vertex_array[0])); + glDrawElements(GL_TRIANGLES, cnt, GL_UNSIGNED_INT, &(index_array[0])); +#endif + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); +} + +//**************************************************************************** +// 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(); + if (cnt == 0) return; + + glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + +#if 0 + glInterleavedArrays(GL_N3F_V3F, 0, vertex_array.data()); + const int32_t* ptr = index_array.data(); +#else + glInterleavedArrays(GL_N3F_V3F, 0, &(vertex_array[0])); + const int32_t* ptr = &(index_array[0]); +#endif + + 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); +} +#else +void SoBrepFaceSet::GLRender(SoGLRenderAction *action) +{ + if (this->coordIndex.getNum() < 3) + return; + if (this->selectionIndex.getNum() > 0) + renderSelection(action); + if (this->highlightIndex.getValue() >= 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; + + SoState * state = action->getState(); + + 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; + int numparts; + 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); + 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 (this->highlightIndex.getValue() >= 0) + renderHighlight(action); + if (this->selectionIndex.getNum() > 0) + renderSelection(action); +//#endif +} +#endif + void SoBrepFaceSet::GLRenderBelowPath(SoGLRenderAction * action) { inherited::GLRenderBelowPath(action); @@ -661,105 +781,6 @@ void SoBrepFaceSet::renderSelection(SoGLRenderAction *action) 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, @@ -928,60 +949,96 @@ void SoBrepFaceSet::renderShape(const SoGLCoordinateElement * const vertexlist, 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() +SoDetail * SoBrepFaceSet::createTriangleDetail(SoRayPickAction * action, + const SoPrimitiveVertex * v1, + const SoPrimitiveVertex * v2, + const SoPrimitiveVertex * v3, + SoPickedPoint * pp) { - 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; + 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; + } } - } - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); + } + return detail; } -#endif -#endif +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; +} diff --git a/src/Mod/Part/Gui/SoBrepFaceSet.h b/src/Mod/Part/Gui/SoBrepFaceSet.h index 9259601a0..74eef1803 100644 --- a/src/Mod/Part/Gui/SoBrepFaceSet.h +++ b/src/Mod/Part/Gui/SoBrepFaceSet.h @@ -22,14 +22,13 @@ #ifndef PARTGUI_SOBREPFACESET_H #define PARTGUI_SOBREPFACESET_H -#if 0 + +#include #include #include #include #include #include -#include -#include #include #include #include @@ -37,14 +36,45 @@ class SoGLCoordinateElement; class SoTextureCoordinateBundle; - +#if 0 #define RENDER_GLARRAYS +#endif namespace PartGui { -class VertexArray; - - +/** + * First some words to the history and the reason why we have this class: + * In older FreeCAD versions we had an own Inventor node for each sub-element of a shape with its own highlight node. + * For more complex objects the number of nodes increased dramatically with the result that interactions with such + * objects was almost impossible because every little rotation or hovering caused a very time consuming redraw. The + * most time consuming part was not the OpenGL calls to render the elements but the traversal of these many nodes. + * + * So, the idea was to have one node that handles all faces of a shape, one node that handles all edges and another node + * that handles the vertexes. And each of these nodes manages the highlighting and selection itself. + * + * Now to SoBrepFaceSet in detail: + * The most complex nodes of them is SoBrepFaceSet because it adds some extra logic for the handling of faces. As you can + * see this class also has the attribute partIndex which is an array of integers. This basically expresses the logical + * grouping of the faces in the coordIndex field -- the parts. This means that a part in SoBrepFaceSet corresponds to a face + * in a shape object. Each part value gives you the number of triangles a certain face consists of. That's also the reason why + * SoBrepFaceSet only renders triangles. If you want a quad to be rendered than create two triangles and set the corresponding + * part number to 2. + * + * Example: + * Let's say you have a shape with two faces. When meshing face 1 it creates 10 triangles and face 2 creates 5 triangles. Then + * the partIndex attribute would be the array [10,5]. + * + * Highlighting/selection: + * The highlightIndex now defines which part of the shape must be highlighted. So, in the above example it can have the values + * 0, 1, or -1 (i.e. no highlighting). The highlightIndex is a SoSFInt32 field because only one part can be highlighted at a + * moment while selectionIndex is a SoMFInt32 field because several parts can be selected at a time. All the logic how to do the + * rendering is done inside renderHighlight()/renderSelection(). + * + * Actually you can access the highlightIndex directly or you can apply a SoHighlightElementAction on it. And don't forget: if you + * do some mouse picking and you got a SoFaceDetail then use getPartIndex() to get the correct part. + * + * As an example how to use the class correctly see ViewProviderPartExt::updateVisual(). + */ class PartGuiExport SoBrepFaceSet : public SoIndexedFaceSet { typedef SoIndexedFaceSet inherited; @@ -58,22 +88,6 @@ public: 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); @@ -88,14 +102,18 @@ protected: virtual void generatePrimitives(SoAction * action); private: + enum Binding { + OVERALL = 0, + PER_PART, + PER_PART_INDEXED, + PER_FACE, + PER_FACE_INDEXED, + PER_VERTEX, + PER_VERTEX_INDEXED, + NONE = OVERALL + }; 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, @@ -110,6 +128,8 @@ private: const int nbind, const int mbind, const int texture); + void renderHighlight(SoGLRenderAction *action); + void renderSelection(SoGLRenderAction *action); #ifdef RENDER_GLARRAYS void renderSimpleArray(); @@ -117,12 +137,16 @@ private: #endif private: +#ifdef RENDER_GLARRAYS + std::vector index_array; + std::vector vertex_array; +#endif SbColor selectionColor; SbColor highlightColor; SoColorPacker colorpacker; }; } // namespace PartGui -#endif + #endif // PARTGUI_SOBREPFACESET_H diff --git a/src/Mod/Part/Gui/SoBrepPointSet.cpp b/src/Mod/Part/Gui/SoBrepPointSet.cpp new file mode 100644 index 000000000..abf7e54b2 --- /dev/null +++ b/src/Mod/Part/Gui/SoBrepPointSet.cpp @@ -0,0 +1,246 @@ +/*************************************************************************** + * 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" + +#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 "SoBrepPointSet.h" +#include +#include + +using namespace PartGui; + + +SO_NODE_SOURCE(SoBrepPointSet); + +void SoBrepPointSet::initClass() +{ + SO_NODE_INIT_CLASS(SoBrepPointSet, SoPointSet, "PointSet"); +} + +SoBrepPointSet::SoBrepPointSet() +{ + SO_NODE_CONSTRUCTOR(SoBrepPointSet); + SO_NODE_ADD_FIELD(highlightIndex, (-1)); + SO_NODE_ADD_FIELD(selectionIndex, (-1)); + selectionIndex.setNum(0); +} + +void SoBrepPointSet::GLRender(SoGLRenderAction *action) +{ + const SoCoordinateElement* coords = SoCoordinateElement::getInstance(action->getState()); + int num = coords->getNum() - this->startIndex.getValue(); + if (num < 0) { + // Fixes: #0000545: Undo revolve causes crash 'illegal storage' + return; + } + if (this->selectionIndex.getNum() > 0) + renderSelection(action); + if (this->highlightIndex.getValue() >= 0) + renderHighlight(action); + inherited::GLRender(action); + + // Workaround for #0000433 +//#if !defined(FC_OS_WIN32) + if (this->highlightIndex.getValue() >= 0) + renderHighlight(action); + if (this->selectionIndex.getNum() > 0) + renderSelection(action); +//#endif +} + +void SoBrepPointSet::GLRenderBelowPath(SoGLRenderAction * action) +{ + inherited::GLRenderBelowPath(action); +} + +void SoBrepPointSet::renderShape(const SoGLCoordinateElement * const coords, + const int32_t *cindices, + int numindices) +{ + const SbVec3f * coords3d = coords->getArrayPtr3(); + + int previ; + const int32_t *end = cindices + numindices; + glBegin(GL_POINTS); + while (cindices < end) { + previ = *cindices++; + glVertex3fv((const GLfloat*) (coords3d + previ)); + } + glEnd(); +} + +void SoBrepPointSet::renderHighlight(SoGLRenderAction *action) +{ + SoState * state = action->getState(); + state->push(); + float ps = SoPointSizeElement::get(state); + if (ps < 4.0f) SoPointSizeElement::set(state, this, 4.0f); + + SoLazyElement::setEmissive(state, &this->highlightColor); + SoOverrideElement::setEmissiveColorOverride(state, this, TRUE); + SoLazyElement::setDiffuse(state, this,1, &this->highlightColor,&this->colorpacker); + SoOverrideElement::setDiffuseColorOverride(state, this, TRUE); + + const SoCoordinateElement * coords; + const SbVec3f * normals; + + this->getVertexData(state, coords, normals, FALSE); + + SoMaterialBundle mb(action); + mb.sendFirst(); // make sure we have the correct material + + int32_t id = this->highlightIndex.getValue(); + + renderShape(static_cast(coords), &id, 1); + state->pop(); +} + +void SoBrepPointSet::renderSelection(SoGLRenderAction *action) +{ + SoState * state = action->getState(); + state->push(); + float ps = SoPointSizeElement::get(state); + if (ps < 4.0f) SoPointSizeElement::set(state, this, 4.0f); + + SoLazyElement::setEmissive(state, &this->selectionColor); + SoOverrideElement::setEmissiveColorOverride(state, this, TRUE); + SoLazyElement::setDiffuse(state, this,1, &this->selectionColor,&this->colorpacker); + SoOverrideElement::setDiffuseColorOverride(state, this, TRUE); + + const SoCoordinateElement * coords; + const SbVec3f * normals; + const int32_t * cindices; + int numcindices; + + this->getVertexData(state, coords, normals, FALSE); + + SoMaterialBundle mb(action); + mb.sendFirst(); // make sure we have the correct material + + cindices = this->selectionIndex.getValues(0); + numcindices = this->selectionIndex.getNum(); + + renderShape(static_cast(coords), cindices, numcindices); + state->pop(); +} + +void SoBrepPointSet::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(SoPointDetail::getClassTypeId())) { + this->highlightIndex = -1; + return; + } + + int index = static_cast(detail)->getCoordinateIndex(); + this->highlightIndex.setValue(index); + this->highlightColor = hlaction->getColor(); + } + } + else if (action->getTypeId() == Gui::SoSelectionElementAction::getClassTypeId()) { + Gui::SoSelectionElementAction* selaction = static_cast(action); + this->selectionColor = selaction->getColor(); + if (selaction->getType() == Gui::SoSelectionElementAction::All) { + const SoCoordinateElement* coords = SoCoordinateElement::getInstance(action->getState()); + int num = coords->getNum() - this->startIndex.getValue(); + this->selectionIndex.setNum(num); + int32_t* v = this->selectionIndex.startEditing(); + int32_t s = this->startIndex.getValue(); + 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(SoPointDetail::getClassTypeId())) { + return; + } + + int index = static_cast(detail)->getCoordinateIndex(); + 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); +} diff --git a/src/Mod/Part/Gui/SoBrepPointSet.h b/src/Mod/Part/Gui/SoBrepPointSet.h new file mode 100644 index 000000000..f83a4a261 --- /dev/null +++ b/src/Mod/Part/Gui/SoBrepPointSet.h @@ -0,0 +1,76 @@ +/*************************************************************************** + * 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_SOBREPPOINTSET_H +#define PARTGUI_SOBREPPOINTSET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class SoGLCoordinateElement; +class SoTextureCoordinateBundle; + +namespace PartGui { + +class PartGuiExport SoBrepPointSet : public SoPointSet { + typedef SoPointSet inherited; + + SO_NODE_HEADER(SoBrepPointSet); + +public: + static void initClass(); + SoBrepPointSet(); + + SoSFInt32 highlightIndex; + SoMFInt32 selectionIndex; + +protected: + virtual ~SoBrepPointSet() {}; + virtual void GLRender(SoGLRenderAction *action); + virtual void GLRenderBelowPath(SoGLRenderAction * action); + virtual void doAction(SoAction* action); + +private: + void renderShape(const SoGLCoordinateElement * const vertexlist, + const int32_t *vertexindices, + int num_vertexindices); + void renderHighlight(SoGLRenderAction *action); + void renderSelection(SoGLRenderAction *action); + +private: + SbColor selectionColor; + SbColor highlightColor; + SoColorPacker colorpacker; +}; + +} // namespace PartGui + + +#endif // PARTGUI_SOBREPPOINTSET_H + diff --git a/src/Mod/Part/Gui/SoBrepShape.cpp b/src/Mod/Part/Gui/SoBrepShape.cpp deleted file mode 100644 index 811710e68..000000000 --- a/src/Mod/Part/Gui/SoBrepShape.cpp +++ /dev/null @@ -1,1344 +0,0 @@ -/*************************************************************************** - * 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" - -#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 "SoBrepShape.h" -#include -#include - -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); -} - -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) -{ - if (this->coordIndex.getNum() < 3) - return; - if (this->selectionIndex.getNum() > 0) - renderSelection(action); - if (this->highlightIndex.getValue() >= 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; - - SoState * state = action->getState(); - - 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; - int numparts; - 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); - 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 (this->highlightIndex.getValue() >= 0) - renderHighlight(action); - if (this->selectionIndex.getNum() > 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(); -} - -void SoBrepFaceSet::renderShape(const SoGLCoordinateElement * const vertexlist, - const int32_t *vertexindices, - int numindices, - 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 + numindices; - 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(); -} - -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; -} - -// --------------------------------------------------------------------- - -SO_NODE_SOURCE(SoBrepEdgeSet); - -void SoBrepEdgeSet::initClass() -{ - SO_NODE_INIT_CLASS(SoBrepEdgeSet, SoIndexedLineSet, "IndexedLineSet"); -} - -SoBrepEdgeSet::SoBrepEdgeSet() -{ - SO_NODE_CONSTRUCTOR(SoBrepEdgeSet); - SO_NODE_ADD_FIELD(highlightIndex, (-1)); - SO_NODE_ADD_FIELD(selectionIndex, (-1)); - selectionIndex.setNum(0); -} - -void SoBrepEdgeSet::GLRender(SoGLRenderAction *action) -{ - if (this->selectionIndex.getNum() > 0) - renderSelection(action); - if (this->highlightIndex.getValue() >= 0) - renderHighlight(action); - inherited::GLRender(action); - - // Workaround for #0000433 -//#if !defined(FC_OS_WIN32) - if (this->highlightIndex.getValue() >= 0) - renderHighlight(action); - if (this->selectionIndex.getNum() > 0) - renderSelection(action); -//#endif -} - -void SoBrepEdgeSet::GLRenderBelowPath(SoGLRenderAction * action) -{ - inherited::GLRenderBelowPath(action); -} - -void SoBrepEdgeSet::renderShape(const SoGLCoordinateElement * const coords, - const int32_t *cindices, int numindices) -{ - - const SbVec3f * coords3d = coords->getArrayPtr3(); - - int32_t i; - int previ; - const int32_t *end = cindices + numindices; - while (cindices < end) { - glBegin(GL_LINE_STRIP); - previ = *cindices++; - i = (cindices < end) ? *cindices++ : -1; - while (i >= 0) { - glVertex3fv((const GLfloat*) (coords3d + previ)); - glVertex3fv((const GLfloat*) (coords3d + i)); - previ = i; - i = cindices < end ? *cindices++ : -1; - } - glEnd(); - } -} - -void SoBrepEdgeSet::renderHighlight(SoGLRenderAction *action) -{ - SoState * state = action->getState(); - state->push(); - //SoLineWidthElement::set(state, this, 4.0f); - - SoLazyElement::setEmissive(state, &this->highlightColor); - SoOverrideElement::setEmissiveColorOverride(state, this, TRUE); - SoLazyElement::setDiffuse(state, this,1, &this->highlightColor,&this->colorpacker1); - SoOverrideElement::setDiffuseColorOverride(state, this, TRUE); - SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR); - - const SoCoordinateElement * coords; - const SbVec3f * normals; - const int32_t * cindices; - int numcindices; - const int32_t * nindices; - const int32_t * tindices; - const int32_t * mindices; - SbBool normalCacheUsed; - - this->getVertexData(state, coords, normals, cindices, nindices, - tindices, mindices, numcindices, FALSE, normalCacheUsed); - - SoMaterialBundle mb(action); - mb.sendFirst(); // make sure we have the correct material - - const int32_t* id = &(this->hl[0]); - int num = (int)this->hl.size(); - - renderShape(static_cast(coords), id, num); - state->pop(); -} - -void SoBrepEdgeSet::renderSelection(SoGLRenderAction *action) -{ - int numSelected = this->selectionIndex.getNum(); - if (numSelected == 0) return; - - SoState * state = action->getState(); - state->push(); - //SoLineWidthElement::set(state, this, 4.0f); - - SoLazyElement::setEmissive(state, &this->selectionColor); - SoOverrideElement::setEmissiveColorOverride(state, this, TRUE); - SoLazyElement::setDiffuse(state, this,1, &this->selectionColor,&this->colorpacker2); - SoOverrideElement::setDiffuseColorOverride(state, this, TRUE); - SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR); - - const SoCoordinateElement * coords; - const SbVec3f * normals; - const int32_t * cindices; - int numcindices; - const int32_t * nindices; - const int32_t * tindices; - const int32_t * mindices; - SbBool normalCacheUsed; - - this->getVertexData(state, coords, normals, cindices, nindices, - tindices, mindices, numcindices, FALSE, normalCacheUsed); - - SoMaterialBundle mb(action); - mb.sendFirst(); // make sure we have the correct material - - cindices = &(this->sl[0]); - numcindices = (int)this->sl.size(); - - renderShape(static_cast(coords), cindices, numcindices); - state->pop(); -} - -static void createIndexArray(const int32_t* segm, int numsegm, - const int32_t* cindices, int numcindices, - std::vector& out) -{ - std::vector v; - for (int j=0; j index) - break; - if (cindices[i] < 0) - section++; - } - - v.insert(v.end(), cindices+start, cindices+start+num); - } - - out.swap(v); -} - -void SoBrepEdgeSet::doAction(SoAction* action) -{ - if (action->getTypeId() == Gui::SoHighlightElementAction::getClassTypeId()) { - Gui::SoHighlightElementAction* hlaction = static_cast(action); - if (!hlaction->isHighlighted()) { - this->highlightIndex = -1; - this->hl.clear(); - return; - } - const SoDetail* detail = hlaction->getElement(); - if (detail) { - if (!detail->isOfType(SoLineDetail::getClassTypeId())) { - this->highlightIndex = -1; - this->hl.clear(); - return; - } - - this->highlightColor = hlaction->getColor(); - int32_t index = static_cast(detail)->getLineIndex(); - const int32_t* cindices = this->coordIndex.getValues(0); - int numcindices = this->coordIndex.getNum(); - - createIndexArray(&index, 1, cindices, numcindices, this->hl); - this->highlightIndex.setValue(index); - } - } - else if (action->getTypeId() == Gui::SoSelectionElementAction::getClassTypeId()) { - Gui::SoSelectionElementAction* selaction = static_cast(action); - - this->selectionColor = selaction->getColor(); - if (selaction->getType() == Gui::SoSelectionElementAction::All) { - const int32_t* cindices = this->coordIndex.getValues(0); - int numcindices = this->coordIndex.getNum(); - unsigned int num = std::count_if(cindices, cindices+numcindices, - std::bind2nd(std::equal_to(), -1)); - - this->sl.clear(); - this->selectionIndex.setNum(num); - int32_t* v = this->selectionIndex.startEditing(); - for (unsigned int i=0; iselectionIndex.finishEditing(); - - int numsegm = this->selectionIndex.getNum(); - if (numsegm > 0) { - const int32_t* selsegm = this->selectionIndex.getValues(0); - const int32_t* cindices = this->coordIndex.getValues(0); - int numcindices = this->coordIndex.getNum(); - createIndexArray(selsegm, numsegm, cindices, numcindices, this->sl); - } - return; - } - else if (selaction->getType() == Gui::SoSelectionElementAction::None) { - this->selectionIndex.setNum(0); - this->sl.clear(); - return; - } - - const SoDetail* detail = selaction->getElement(); - if (detail) { - if (!detail->isOfType(SoLineDetail::getClassTypeId())) { - return; - } - - int index = static_cast(detail)->getLineIndex(); - 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; - } - - int numsegm = this->selectionIndex.getNum(); - if (numsegm > 0) { - const int32_t* selsegm = this->selectionIndex.getValues(0); - const int32_t* cindices = this->coordIndex.getValues(0); - int numcindices = this->coordIndex.getNum(); - createIndexArray(selsegm, numsegm, cindices, numcindices, this->sl); - } - } - } - - inherited::doAction(action); -} - -SoDetail * SoBrepEdgeSet::createLineSegmentDetail(SoRayPickAction * action, - const SoPrimitiveVertex * v1, - const SoPrimitiveVertex * v2, - SoPickedPoint * pp) -{ - SoDetail* detail = inherited::createLineSegmentDetail(action, v1, v2, pp); - SoLineDetail* line_detail = static_cast(detail); - int index = line_detail->getLineIndex(); - line_detail->setPartIndex(index); - return detail; -} - -// --------------------------------------------------------------------- - -SO_NODE_SOURCE(SoBrepPointSet); - -void SoBrepPointSet::initClass() -{ - SO_NODE_INIT_CLASS(SoBrepPointSet, SoPointSet, "PointSet"); -} - -SoBrepPointSet::SoBrepPointSet() -{ - SO_NODE_CONSTRUCTOR(SoBrepPointSet); - SO_NODE_ADD_FIELD(highlightIndex, (-1)); - SO_NODE_ADD_FIELD(selectionIndex, (-1)); - selectionIndex.setNum(0); -} - -void SoBrepPointSet::GLRender(SoGLRenderAction *action) -{ - const SoCoordinateElement* coords = SoCoordinateElement::getInstance(action->getState()); - int num = coords->getNum() - this->startIndex.getValue(); - if (num < 0) { - // Fixes: #0000545: Undo revolve causes crash 'illegal storage' - return; - } - if (this->selectionIndex.getNum() > 0) - renderSelection(action); - if (this->highlightIndex.getValue() >= 0) - renderHighlight(action); - inherited::GLRender(action); - - // Workaround for #0000433 -//#if !defined(FC_OS_WIN32) - if (this->highlightIndex.getValue() >= 0) - renderHighlight(action); - if (this->selectionIndex.getNum() > 0) - renderSelection(action); -//#endif -} - -void SoBrepPointSet::GLRenderBelowPath(SoGLRenderAction * action) -{ - inherited::GLRenderBelowPath(action); -} - -void SoBrepPointSet::renderShape(const SoGLCoordinateElement * const coords, - const int32_t *cindices, - int numindices) -{ - const SbVec3f * coords3d = coords->getArrayPtr3(); - - int previ; - const int32_t *end = cindices + numindices; - glBegin(GL_POINTS); - while (cindices < end) { - previ = *cindices++; - glVertex3fv((const GLfloat*) (coords3d + previ)); - } - glEnd(); -} - -void SoBrepPointSet::renderHighlight(SoGLRenderAction *action) -{ - SoState * state = action->getState(); - state->push(); - float ps = SoPointSizeElement::get(state); - if (ps < 4.0f) SoPointSizeElement::set(state, this, 4.0f); - - SoLazyElement::setEmissive(state, &this->highlightColor); - SoOverrideElement::setEmissiveColorOverride(state, this, TRUE); - SoLazyElement::setDiffuse(state, this,1, &this->highlightColor,&this->colorpacker); - SoOverrideElement::setDiffuseColorOverride(state, this, TRUE); - - const SoCoordinateElement * coords; - const SbVec3f * normals; - - this->getVertexData(state, coords, normals, FALSE); - - SoMaterialBundle mb(action); - mb.sendFirst(); // make sure we have the correct material - - int32_t id = this->highlightIndex.getValue(); - - renderShape(static_cast(coords), &id, 1); - state->pop(); -} - -void SoBrepPointSet::renderSelection(SoGLRenderAction *action) -{ - SoState * state = action->getState(); - state->push(); - float ps = SoPointSizeElement::get(state); - if (ps < 4.0f) SoPointSizeElement::set(state, this, 4.0f); - - SoLazyElement::setEmissive(state, &this->selectionColor); - SoOverrideElement::setEmissiveColorOverride(state, this, TRUE); - SoLazyElement::setDiffuse(state, this,1, &this->selectionColor,&this->colorpacker); - SoOverrideElement::setDiffuseColorOverride(state, this, TRUE); - - const SoCoordinateElement * coords; - const SbVec3f * normals; - const int32_t * cindices; - int numcindices; - - this->getVertexData(state, coords, normals, FALSE); - - SoMaterialBundle mb(action); - mb.sendFirst(); // make sure we have the correct material - - cindices = this->selectionIndex.getValues(0); - numcindices = this->selectionIndex.getNum(); - - renderShape(static_cast(coords), cindices, numcindices); - state->pop(); -} - -void SoBrepPointSet::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(SoPointDetail::getClassTypeId())) { - this->highlightIndex = -1; - return; - } - - int index = static_cast(detail)->getCoordinateIndex(); - this->highlightIndex.setValue(index); - this->highlightColor = hlaction->getColor(); - } - } - else if (action->getTypeId() == Gui::SoSelectionElementAction::getClassTypeId()) { - Gui::SoSelectionElementAction* selaction = static_cast(action); - this->selectionColor = selaction->getColor(); - if (selaction->getType() == Gui::SoSelectionElementAction::All) { - const SoCoordinateElement* coords = SoCoordinateElement::getInstance(action->getState()); - int num = coords->getNum() - this->startIndex.getValue(); - this->selectionIndex.setNum(num); - int32_t* v = this->selectionIndex.startEditing(); - int32_t s = this->startIndex.getValue(); - 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(SoPointDetail::getClassTypeId())) { - return; - } - - int index = static_cast(detail)->getCoordinateIndex(); - 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); -} diff --git a/src/Mod/Part/Gui/SoBrepShape.h b/src/Mod/Part/Gui/SoBrepShape.h deleted file mode 100644 index 8a3a4eb36..000000000 --- a/src/Mod/Part/Gui/SoBrepShape.h +++ /dev/null @@ -1,215 +0,0 @@ -/*************************************************************************** - * 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_SOBREPSHAPE_H -#define PARTGUI_SOBREPSHAPE_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class SoGLCoordinateElement; -class SoTextureCoordinateBundle; - -namespace PartGui { - -/** - * First some words to the history and the reason why we have this class: - * In older FreeCAD versions we had an own Inventor node for each sub-element of a shape with its own highlight node. - * For more complex objects the number of nodes increased dramatically with the result that interactions with such - * objects was almost impossible because every little rotation or hovering caused a very time consuming redraw. The - * most time consuming part was not the OpenGL calls to render the elements but the traversal of these many nodes. - * - * So, the idea was to have one node that handles all faces of a shape, one node that handles all edges and another node - * that handles the vertexes. And each of these nodes manages the highlighting and selection itself. - * - * Now to SoBrepFaceSet in detail: - * The most complex nodes of them is SoBrepFaceSet because it adds some extra logic for the handling of faces. As you can - * see this class also has the attribute partIndex which is an array of integers. This basically expresses the logical - * grouping of the faces in the coordIndex field -- the parts. This means that a part in SoBrepFaceSet corresponds to a face - * in a shape object. Each part value gives you the number of triangles a certain face consists of. That's also the reason why - * SoBrepFaceSet only renders triangles. If you want a quad to be rendered than create two triangles and set the corresponding - * part number to 2. - * - * Example: - * Let's say you have a shape with two faces. When meshing face 1 it creates 10 triangles and face 2 creates 5 triangles. Then - * the partIndex attribute would be the array [10,5]. - * - * Highlighting/selection: - * The highlightIndex now defines which part of the shape must be highlighted. So, in the above example it can have the values - * 0, 1, or -1 (i.e. no highlighting). The highlightIndex is a SoSFInt32 field because only one part can be highlighted at a - * moment while selectionIndex is a SoMFInt32 field because several parts can be selected at a time. All the logic how to do the - * rendering is done inside renderHighlight()/renderSelection(). - * - * Actually you can access the highlightIndex directly or you can apply a SoHighlightElementAction on it. And don't forget: if you - * do some mouse picking and you got a SoFaceDetail then use getPartIndex() to get the correct part. - * - * As an example how to use the class correctly see ViewProviderPartExt::updateVisual(). - */ -class PartGuiExport SoBrepFaceSet : public SoIndexedFaceSet { - typedef SoIndexedFaceSet inherited; - - SO_NODE_HEADER(SoBrepFaceSet); - -public: - static void initClass(); - SoBrepFaceSet(); - - SoMFInt32 partIndex; - SoSFInt32 highlightIndex; - SoMFInt32 selectionIndex; - -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: - enum Binding { - OVERALL = 0, - PER_PART, - PER_PART_INDEXED, - PER_FACE, - PER_FACE_INDEXED, - PER_VERTEX, - PER_VERTEX_INDEXED, - NONE = OVERALL - }; - Binding findMaterialBinding(SoState * const state) const; - Binding findNormalBinding(SoState * const state) const; - 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); - void renderHighlight(SoGLRenderAction *action); - void renderSelection(SoGLRenderAction *action); - -private: - SbColor selectionColor; - SbColor highlightColor; - SoColorPacker colorpacker; -}; - -// --------------------------------------------------------------------- - -class PartGuiExport SoBrepEdgeSet : public SoIndexedLineSet { - typedef SoIndexedLineSet inherited; - - SO_NODE_HEADER(SoBrepEdgeSet); - -public: - static void initClass(); - SoBrepEdgeSet(); - - SoSFInt32 highlightIndex; - SoMFInt32 selectionIndex; - -protected: - virtual ~SoBrepEdgeSet() {}; - virtual void GLRender(SoGLRenderAction *action); - virtual void GLRenderBelowPath(SoGLRenderAction * action); - virtual void doAction(SoAction* action); - virtual SoDetail * createLineSegmentDetail( - SoRayPickAction *action, - const SoPrimitiveVertex *v1, - const SoPrimitiveVertex *v2, - SoPickedPoint *pp); -private: - void renderShape(const SoGLCoordinateElement * const vertexlist, - const int32_t *vertexindices, - int num_vertexindices); - void renderHighlight(SoGLRenderAction *action); - void renderSelection(SoGLRenderAction *action); - -private: - std::vector hl, sl; - SbColor selectionColor; - SbColor highlightColor; - //#0000834: Minor preselection color bug - //To solve this we need a seprate color packer for highlighting and selection - SoColorPacker colorpacker1; - SoColorPacker colorpacker2; -}; - -// --------------------------------------------------------------------- - -class PartGuiExport SoBrepPointSet : public SoPointSet { - typedef SoPointSet inherited; - - SO_NODE_HEADER(SoBrepPointSet); - -public: - static void initClass(); - SoBrepPointSet(); - - SoSFInt32 highlightIndex; - SoMFInt32 selectionIndex; - -protected: - virtual ~SoBrepPointSet() {}; - virtual void GLRender(SoGLRenderAction *action); - virtual void GLRenderBelowPath(SoGLRenderAction * action); - virtual void doAction(SoAction* action); - -private: - void renderShape(const SoGLCoordinateElement * const vertexlist, - const int32_t *vertexindices, - int num_vertexindices); - void renderHighlight(SoGLRenderAction *action); - void renderSelection(SoGLRenderAction *action); - -private: - SbColor selectionColor; - SbColor highlightColor; - SoColorPacker colorpacker; -}; - -} // namespace PartGui - - -#endif // PARTGUI_SOBREPSHAPE_H - diff --git a/src/Mod/Part/Gui/TaskFaceColors.cpp b/src/Mod/Part/Gui/TaskFaceColors.cpp index 60570612f..88cbbcebc 100644 --- a/src/Mod/Part/Gui/TaskFaceColors.cpp +++ b/src/Mod/Part/Gui/TaskFaceColors.cpp @@ -49,7 +49,7 @@ #include "ui_TaskFaceColors.h" #include "TaskFaceColors.h" #include "ViewProviderExt.h" -#include "SoBrepShape.h" +#include "SoBrepFaceSet.h" #include #include diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index fa14bdebf..8606d5add 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -101,7 +101,8 @@ #include #include "ViewProviderExt.h" -#include "SoBrepShape.h" +#include "SoBrepPointSet.h" +#include "SoBrepEdgeSet.h" #include "SoBrepFaceSet.h" #include "TaskFaceColors.h"