+ Split SoBrepShape into three files

This commit is contained in:
wmayer 2013-11-09 13:16:42 +01:00
parent 909f7d6c13
commit 8e6bd39857
13 changed files with 1029 additions and 1766 deletions

View File

@ -24,8 +24,9 @@
#include <Mod/Part/App/PropertyTopoShape.h> #include <Mod/Part/App/PropertyTopoShape.h>
#include "SoBrepShape.h"
#include "SoBrepFaceSet.h" #include "SoBrepFaceSet.h"
#include "SoBrepEdgeSet.h"
#include "SoBrepPointSet.h"
#include "SoFCShapeObject.h" #include "SoFCShapeObject.h"
#include "ViewProvider.h" #include "ViewProvider.h"
#include "ViewProviderExt.h" #include "ViewProviderExt.h"

View File

@ -131,10 +131,12 @@ SET(PartGui_SRCS
PreCompiled.h PreCompiled.h
SoFCShapeObject.cpp SoFCShapeObject.cpp
SoFCShapeObject.h SoFCShapeObject.h
SoBrepShape.cpp SoBrepEdgeSet.cpp
SoBrepShape.h SoBrepEdgeSet.h
SoBrepFaceSet.cpp SoBrepFaceSet.cpp
SoBrepFaceSet.h SoBrepFaceSet.h
SoBrepPointSet.cpp
SoBrepPointSet.h
ViewProvider.cpp ViewProvider.cpp
ViewProvider.h ViewProvider.h
ViewProviderExt.cpp ViewProviderExt.cpp

View File

@ -49,7 +49,10 @@
#include "DlgFilletEdges.h" #include "DlgFilletEdges.h"
#include "ui_DlgFilletEdges.h" #include "ui_DlgFilletEdges.h"
#include "SoBrepShape.h" #include "SoBrepFaceSet.h"
#include "SoBrepEdgeSet.h"
#include "SoBrepPointSet.h"
#include "../App/PartFeature.h" #include "../App/PartFeature.h"
#include "../App/FeatureFillet.h" #include "../App/FeatureFillet.h"

View File

@ -0,0 +1,328 @@
/***************************************************************************
* Copyright (c) 2011 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* 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 <windows.h>
# endif
# ifdef FC_OS_MACOSX
# include <OpenGL/gl.h>
# else
# include <GL/gl.h>
# endif
# include <float.h>
# include <algorithm>
# include <Inventor/SoPickedPoint.h>
# include <Inventor/SoPrimitiveVertex.h>
# include <Inventor/actions/SoCallbackAction.h>
# include <Inventor/actions/SoGetBoundingBoxAction.h>
# include <Inventor/actions/SoGetPrimitiveCountAction.h>
# include <Inventor/actions/SoGLRenderAction.h>
# include <Inventor/actions/SoPickAction.h>
# include <Inventor/actions/SoWriteAction.h>
# include <Inventor/bundles/SoMaterialBundle.h>
# include <Inventor/bundles/SoTextureCoordinateBundle.h>
# include <Inventor/elements/SoOverrideElement.h>
# include <Inventor/elements/SoCoordinateElement.h>
# include <Inventor/elements/SoGLCoordinateElement.h>
# include <Inventor/elements/SoGLCacheContextElement.h>
# include <Inventor/elements/SoLineWidthElement.h>
# include <Inventor/elements/SoPointSizeElement.h>
# include <Inventor/errors/SoReadError.h>
# include <Inventor/details/SoFaceDetail.h>
# include <Inventor/details/SoLineDetail.h>
# include <Inventor/misc/SoState.h>
#endif
#include "SoBrepEdgeSet.h"
#include <Gui/SoFCUnifiedSelection.h>
#include <Gui/SoFCSelectionAction.h>
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<const SoGLCoordinateElement*>(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<const SoGLCoordinateElement*>(coords), cindices, numcindices);
state->pop();
}
static void createIndexArray(const int32_t* segm, int numsegm,
const int32_t* cindices, int numcindices,
std::vector<int32_t>& out)
{
std::vector<int32_t> v;
for (int j=0; j<numsegm; j++) {
int index = segm[j];
int start=0, num=0;
int section=0;
for (int i=0;i<numcindices;i++) {
if (section < index)
start++;
else if (section == index)
num++;
else if (section > 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<Gui::SoHighlightElementAction*>(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<const SoLineDetail*>(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<Gui::SoSelectionElementAction*>(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<int32_t>(), -1));
this->sl.clear();
this->selectionIndex.setNum(num);
int32_t* v = this->selectionIndex.startEditing();
for (unsigned int i=0; i<num;i++)
v[i] = i;
this->selectionIndex.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<const SoLineDetail*>(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<SoLineDetail*>(detail);
int index = line_detail->getLineIndex();
line_detail->setPartIndex(index);
return detail;
}

View File

@ -0,0 +1,84 @@
/***************************************************************************
* Copyright (c) 2011 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* 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 <Inventor/fields/SoSFInt32.h>
#include <Inventor/fields/SoMFInt32.h>
#include <Inventor/fields/SoSFNode.h>
#include <Inventor/fields/SoSubField.h>
#include <Inventor/nodes/SoSubNode.h>
#include <Inventor/nodes/SoIndexedLineSet.h>
#include <Inventor/elements/SoLazyElement.h>
#include <Inventor/elements/SoReplacedElement.h>
#include <vector>
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<int32_t> 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

View File

@ -22,7 +22,7 @@
#include "PreCompiled.h" #include "PreCompiled.h"
#if 0
#ifndef _PreComp_ #ifndef _PreComp_
# ifdef FC_OS_WIN32 # ifdef FC_OS_WIN32
# include <windows.h> # include <windows.h>
@ -56,12 +56,9 @@
# include <Inventor/misc/SoState.h> # include <Inventor/misc/SoState.h>
#endif #endif
#include "SoBrepFaceSet.h"
#include <Gui/SoFCUnifiedSelection.h> #include <Gui/SoFCUnifiedSelection.h>
#include <Gui/SoFCSelectionAction.h> #include <Gui/SoFCSelectionAction.h>
#include <Base/Console.h>
#include "SoBrepFaceSet.h"
using namespace PartGui; using namespace PartGui;
@ -83,12 +80,10 @@ SoBrepFaceSet::SoBrepFaceSet()
selectionIndex.setNum(0); selectionIndex.setNum(0);
} }
SoBrepFaceSet::~SoBrepFaceSet() SoBrepFaceSet::~SoBrepFaceSet()
{ {
} }
void SoBrepFaceSet::doAction(SoAction* action) void SoBrepFaceSet::doAction(SoAction* action)
{ {
if (action->getTypeId() == Gui::SoHighlightElementAction::getClassTypeId()) { if (action->getTypeId() == Gui::SoHighlightElementAction::getClassTypeId()) {
@ -157,6 +152,7 @@ void SoBrepFaceSet::doAction(SoAction* action)
inherited::doAction(action); inherited::doAction(action);
} }
#ifdef RENDER_GLARRAYS
void SoBrepFaceSet::GLRender(SoGLRenderAction *action) void SoBrepFaceSet::GLRender(SoGLRenderAction *action)
{ {
SoState * state = action->getState(); SoState * state = action->getState();
@ -167,8 +163,8 @@ void SoBrepFaceSet::GLRender(SoGLRenderAction *action)
SoTextureCoordinateBundle tb(action, TRUE, FALSE); SoTextureCoordinateBundle tb(action, TRUE, FALSE);
SbBool doTextures = tb.needCoordinates(); SbBool doTextures = tb.needCoordinates();
int32_t hl_idx = this->highlightIndex.getValue(); int32_t hl_idx = this->highlightIndex.getValue();
int32_t num_selected = this->selectionIndex.getNum(); int32_t num_selected = this->selectionIndex.getNum();
if (this->coordIndex.getNum() < 3) if (this->coordIndex.getNum() < 3)
return; return;
@ -184,17 +180,17 @@ void SoBrepFaceSet::GLRender(SoGLRenderAction *action)
return; return;
#ifdef RENDER_GLARRAYS #ifdef RENDER_GLARRAYS
if (!doTextures && index_array.size() && hl_idx < 0 && num_selected <= 0) { if (!doTextures && index_array.size() && hl_idx < 0 && num_selected <= 0) {
if (mbind == 0) { if (mbind == 0) {
mb.sendFirst(); // only one material -> apply it! mb.sendFirst(); // only one material -> apply it!
renderSimpleArray(); renderSimpleArray();
return; return;
} }
else if (mbind == 1) { else if (mbind == 1) {
renderColoredArray(&mb); renderColoredArray(&mb);
return; return;
} }
} }
#endif #endif
Binding nbind = this->findNormalBinding(state); Binding nbind = this->findNormalBinding(state);
@ -239,6 +235,130 @@ void SoBrepFaceSet::GLRender(SoGLRenderAction *action)
//#endif //#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<const SoGLCoordinateElement*>(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) void SoBrepFaceSet::GLRenderBelowPath(SoGLRenderAction * action)
{ {
inherited::GLRenderBelowPath(action); inherited::GLRenderBelowPath(action);
@ -661,105 +781,6 @@ void SoBrepFaceSet::renderSelection(SoGLRenderAction *action)
state->pop(); 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<SoFaceDetail*>(detail);
int index = face_detail->getFaceIndex();
int count = 0;
for (int i=0; i<num; i++) {
count += indices[i];
if (index < count) {
face_detail->setPartIndex(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, void SoBrepFaceSet::renderShape(const SoGLCoordinateElement * const vertexlist,
const int32_t *vertexindices, const int32_t *vertexindices,
int num_indices, int num_indices,
@ -928,60 +949,96 @@ void SoBrepFaceSet::renderShape(const SoGLCoordinateElement * const vertexlist,
glEnd(); glEnd();
} }
SoDetail * SoBrepFaceSet::createTriangleDetail(SoRayPickAction * action,
#ifdef RENDER_GLARRAYS const SoPrimitiveVertex * v1,
//**************************************************************************** const SoPrimitiveVertex * v2,
// renderSimpleArray: normal and coord from vertex_array; const SoPrimitiveVertex * v3,
// no texture, color, highlight or selection but highet possible speed; SoPickedPoint * pp)
// all vertices written in one go!
//
void SoBrepFaceSet::renderSimpleArray()
{ {
int cnt = index_array.size(); SoDetail* detail = inherited::createTriangleDetail(action, v1, v2, v3, pp);
const int32_t * indices = this->partIndex.getValues(0);
glEnableClientState(GL_NORMAL_ARRAY); int num = this->partIndex.getNum();
glEnableClientState(GL_VERTEX_ARRAY); if (indices) {
SoFaceDetail* face_detail = static_cast<SoFaceDetail*>(detail);
glInterleavedArrays(GL_N3F_V3F, 0, vertex_array.data()); int index = face_detail->getFaceIndex();
glDrawElements(GL_TRIANGLES, cnt, GL_UNSIGNED_INT, index_array.data()); int count = 0;
for (int i=0; i<num; i++) {
glDisableClientState(GL_VERTEX_ARRAY); count += indices[i];
glDisableClientState(GL_NORMAL_ARRAY); if (index < count) {
} face_detail->setPartIndex(i);
#endif break;
}
#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;
} }
} }
return detail;
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
} }
#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;
}

View File

@ -22,14 +22,13 @@
#ifndef PARTGUI_SOBREPFACESET_H #ifndef PARTGUI_SOBREPFACESET_H
#define PARTGUI_SOBREPFACESET_H #define PARTGUI_SOBREPFACESET_H
#if 0
#include <Inventor/fields/SoSFInt32.h>
#include <Inventor/fields/SoMFInt32.h> #include <Inventor/fields/SoMFInt32.h>
#include <Inventor/fields/SoSFNode.h> #include <Inventor/fields/SoSFNode.h>
#include <Inventor/fields/SoSubField.h> #include <Inventor/fields/SoSubField.h>
#include <Inventor/nodes/SoSubNode.h> #include <Inventor/nodes/SoSubNode.h>
#include <Inventor/nodes/SoIndexedFaceSet.h> #include <Inventor/nodes/SoIndexedFaceSet.h>
#include <Inventor/nodes/SoIndexedLineSet.h>
#include <Inventor/nodes/SoPointSet.h>
#include <Inventor/elements/SoLazyElement.h> #include <Inventor/elements/SoLazyElement.h>
#include <Inventor/elements/SoReplacedElement.h> #include <Inventor/elements/SoReplacedElement.h>
#include <vector> #include <vector>
@ -37,14 +36,45 @@
class SoGLCoordinateElement; class SoGLCoordinateElement;
class SoTextureCoordinateBundle; class SoTextureCoordinateBundle;
#if 0
#define RENDER_GLARRAYS #define RENDER_GLARRAYS
#endif
namespace PartGui { 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 { class PartGuiExport SoBrepFaceSet : public SoIndexedFaceSet {
typedef SoIndexedFaceSet inherited; typedef SoIndexedFaceSet inherited;
@ -58,22 +88,6 @@ public:
SoSFInt32 highlightIndex; SoSFInt32 highlightIndex;
SoMFInt32 selectionIndex; SoMFInt32 selectionIndex;
#ifdef RENDER_GLARRAYS
std::vector<int32_t> index_array;
std::vector<float> 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: protected:
virtual ~SoBrepFaceSet(); virtual ~SoBrepFaceSet();
virtual void GLRender(SoGLRenderAction *action); virtual void GLRender(SoGLRenderAction *action);
@ -88,14 +102,18 @@ protected:
virtual void generatePrimitives(SoAction * action); virtual void generatePrimitives(SoAction * action);
private: 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 findMaterialBinding(SoState * const state) const;
Binding findNormalBinding(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, void renderShape(const SoGLCoordinateElement * const vertexlist,
const int32_t *vertexindices, const int32_t *vertexindices,
int num_vertexindices, int num_vertexindices,
@ -110,6 +128,8 @@ private:
const int nbind, const int nbind,
const int mbind, const int mbind,
const int texture); const int texture);
void renderHighlight(SoGLRenderAction *action);
void renderSelection(SoGLRenderAction *action);
#ifdef RENDER_GLARRAYS #ifdef RENDER_GLARRAYS
void renderSimpleArray(); void renderSimpleArray();
@ -117,12 +137,16 @@ private:
#endif #endif
private: private:
#ifdef RENDER_GLARRAYS
std::vector<int32_t> index_array;
std::vector<float> vertex_array;
#endif
SbColor selectionColor; SbColor selectionColor;
SbColor highlightColor; SbColor highlightColor;
SoColorPacker colorpacker; SoColorPacker colorpacker;
}; };
} // namespace PartGui } // namespace PartGui
#endif
#endif // PARTGUI_SOBREPFACESET_H #endif // PARTGUI_SOBREPFACESET_H

View File

@ -0,0 +1,246 @@
/***************************************************************************
* Copyright (c) 2011 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* 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 <windows.h>
# endif
# ifdef FC_OS_MACOSX
# include <OpenGL/gl.h>
# else
# include <GL/gl.h>
# endif
# include <float.h>
# include <algorithm>
# include <Inventor/SoPickedPoint.h>
# include <Inventor/SoPrimitiveVertex.h>
# include <Inventor/actions/SoCallbackAction.h>
# include <Inventor/actions/SoGetBoundingBoxAction.h>
# include <Inventor/actions/SoGetPrimitiveCountAction.h>
# include <Inventor/actions/SoGLRenderAction.h>
# include <Inventor/actions/SoPickAction.h>
# include <Inventor/actions/SoWriteAction.h>
# include <Inventor/bundles/SoMaterialBundle.h>
# include <Inventor/bundles/SoTextureCoordinateBundle.h>
# include <Inventor/elements/SoOverrideElement.h>
# include <Inventor/elements/SoCoordinateElement.h>
# include <Inventor/elements/SoGLCoordinateElement.h>
# include <Inventor/elements/SoGLCacheContextElement.h>
# include <Inventor/elements/SoLineWidthElement.h>
# include <Inventor/elements/SoPointSizeElement.h>
# include <Inventor/errors/SoReadError.h>
# include <Inventor/details/SoFaceDetail.h>
# include <Inventor/details/SoLineDetail.h>
# include <Inventor/misc/SoState.h>
#endif
#include "SoBrepPointSet.h"
#include <Gui/SoFCUnifiedSelection.h>
#include <Gui/SoFCSelectionAction.h>
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<const SoGLCoordinateElement*>(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<const SoGLCoordinateElement*>(coords), cindices, numcindices);
state->pop();
}
void SoBrepPointSet::doAction(SoAction* action)
{
if (action->getTypeId() == Gui::SoHighlightElementAction::getClassTypeId()) {
Gui::SoHighlightElementAction* hlaction = static_cast<Gui::SoHighlightElementAction*>(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<const SoPointDetail*>(detail)->getCoordinateIndex();
this->highlightIndex.setValue(index);
this->highlightColor = hlaction->getColor();
}
}
else if (action->getTypeId() == Gui::SoSelectionElementAction::getClassTypeId()) {
Gui::SoSelectionElementAction* selaction = static_cast<Gui::SoSelectionElementAction*>(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; i<num;i++)
v[i] = i + s;
this->selectionIndex.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<const SoPointDetail*>(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);
}

View File

@ -0,0 +1,76 @@
/***************************************************************************
* Copyright (c) 2011 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* 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 <Inventor/fields/SoSFInt32.h>
#include <Inventor/fields/SoMFInt32.h>
#include <Inventor/fields/SoSFNode.h>
#include <Inventor/fields/SoSubField.h>
#include <Inventor/nodes/SoSubNode.h>
#include <Inventor/nodes/SoPointSet.h>
#include <Inventor/elements/SoLazyElement.h>
#include <Inventor/elements/SoReplacedElement.h>
#include <vector>
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

File diff suppressed because it is too large Load Diff

View File

@ -1,215 +0,0 @@
/***************************************************************************
* Copyright (c) 2011 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* 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 <Inventor/fields/SoMFInt32.h>
#include <Inventor/fields/SoSFNode.h>
#include <Inventor/fields/SoSubField.h>
#include <Inventor/nodes/SoSubNode.h>
#include <Inventor/nodes/SoIndexedFaceSet.h>
#include <Inventor/nodes/SoIndexedLineSet.h>
#include <Inventor/nodes/SoPointSet.h>
#include <Inventor/elements/SoLazyElement.h>
#include <Inventor/elements/SoReplacedElement.h>
#include <vector>
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<int32_t> 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

View File

@ -49,7 +49,7 @@
#include "ui_TaskFaceColors.h" #include "ui_TaskFaceColors.h"
#include "TaskFaceColors.h" #include "TaskFaceColors.h"
#include "ViewProviderExt.h" #include "ViewProviderExt.h"
#include "SoBrepShape.h" #include "SoBrepFaceSet.h"
#include <Gui/Application.h> #include <Gui/Application.h>
#include <Gui/Control.h> #include <Gui/Control.h>

View File

@ -101,7 +101,8 @@
#include <Gui/Control.h> #include <Gui/Control.h>
#include "ViewProviderExt.h" #include "ViewProviderExt.h"
#include "SoBrepShape.h" #include "SoBrepPointSet.h"
#include "SoBrepEdgeSet.h"
#include "SoBrepFaceSet.h" #include "SoBrepFaceSet.h"
#include "TaskFaceColors.h" #include "TaskFaceColors.h"