changes in Mesh module:

+ cppcheck: fix some minor issues found by code analyzer
+ export to IDTF
+ fix for throwing exception
+ optimize mesh rendering
This commit is contained in:
wmayer
2017-11-08 17:56:13 +01:00
parent 547af2f5b2
commit def0b81784
15 changed files with 508 additions and 17 deletions

View File

@@ -28,6 +28,7 @@
#include <Mod/Mesh/App/WildMagic4/Wm4QuadricSurface.h>
#include <Mod/Mesh/App/WildMagic4/Wm4Eigen.h>
#include <Mod/Mesh/App/WildMagic4/Wm4ImplicitSurface.h>
#include <algorithm>
#include <list>
#include <set>
#include <vector>
@@ -260,7 +261,9 @@ public:
/**
* Construction
*/
QuadraticFit() : Approximation() {};
QuadraticFit() : Approximation() {
std::fill(_fCoeff, _fCoeff+10, 0.0);
}
/**
* Destruction
*/

View File

@@ -1610,6 +1610,12 @@ MeshIO::Format MeshOutput::GetFormat(const char* FileName)
else if (file.hasExtension("ply")) {
return MeshIO::PLY;
}
else if (file.hasExtension("idtf")) {
return MeshIO::IDTF;
}
else if (file.hasExtension("mgl")) {
return MeshIO::MGL;
}
else if (file.hasExtension("iv")) {
return MeshIO::IV;
}
@@ -1676,7 +1682,6 @@ bool MeshOutput::SaveAny(const char* FileName, MeshIO::Format format) const
ok = aWriter.SaveAsciiSTL( str );
if (!ok)
throw Base::FileException("Export of STL mesh failed",FileName);
}
else if (fileformat == MeshIO::OBJ) {
// write file
@@ -1698,6 +1703,16 @@ bool MeshOutput::SaveAny(const char* FileName, MeshIO::Format format) const
if (!SaveAsciiPLY(str))
throw Base::FileException("Export of PLY mesh failed",FileName);
}
else if (fileformat == MeshIO::IDTF) {
// write file
if (!SaveIDTF(str))
throw Base::FileException("Export of IDTF mesh failed",FileName);
}
else if (fileformat == MeshIO::MGL) {
// write file
if (!SaveMGL(str))
throw Base::FileException("Export of MGL mesh failed",FileName);
}
else if (fileformat == MeshIO::IV) {
// write file
if (!SaveInventor(str))
@@ -1756,6 +1771,10 @@ bool MeshOutput::SaveFormat(std::ostream &str, MeshIO::Format fmt) const
return SaveOBJ(str);
case MeshIO::OFF:
return SaveOFF(str);
case MeshIO::IDTF:
return SaveIDTF(str);
case MeshIO::MGL:
return SaveMGL(str);
case MeshIO::IV:
return SaveInventor(str);
case MeshIO::X3D:
@@ -2403,6 +2422,152 @@ void MeshOutput::SaveXML (Base::Writer &writer) const
writer.decInd();
}
/** Writes an IDTF file. */
bool MeshOutput::SaveIDTF (std::ostream &str) const
{
if ((!str) || (str.bad() == true) || (_rclMesh.CountFacets() == 0))
return false;
const MeshPointArray& pts = _rclMesh.GetPoints();
const MeshFacetArray& fts = _rclMesh.GetFacets();
std::string resource = objectName;
if (resource.empty())
resource = "Resource";
str.precision(6);
str.setf(std::ios::fixed | std::ios::showpoint);
str << "FILE_FORMAT \"IDTF\"" << std::endl
<< "FORMAT_VERSION 100" << std::endl << std::endl;
str << Base::tabs(0) << "NODE \"MODEL\" {" << std::endl;
str << Base::tabs(1) << "NODE_NAME \"FreeCAD\"" << std::endl;
str << Base::tabs(1) << "PARENT_LIST {" << std::endl;
str << Base::tabs(2) << "PARENT_COUNT 1" << std::endl;
str << Base::tabs(2) << "PARENT 0 {" << std::endl;
str << Base::tabs(3) << "PARENT_NAME \"<NULL>\"" << std::endl;
str << Base::tabs(3) << "PARENT_TM {" << std::endl;
str << Base::tabs(4) << "1.000000 0.000000 0.000000 0.000000" << std::endl;
str << Base::tabs(4) << "0.000000 1.000000 0.000000 0.000000" << std::endl;
str << Base::tabs(4) << "0.000000 0.000000 1.000000 0.000000" << std::endl;
str << Base::tabs(4) << "0.000000 0.000000 0.000000 1.000000" << std::endl;
str << Base::tabs(3) << "}" << std::endl;
str << Base::tabs(2) << "}" << std::endl;
str << Base::tabs(1) << "}" << std::endl;
str << Base::tabs(1) << "RESOURCE_NAME \"FreeCAD\"" << std::endl;
str << Base::tabs(0) << "}" << std::endl << std::endl;
str << Base::tabs(0) << "RESOURCE_LIST \"MODEL\" {" << std::endl;
str << Base::tabs(1) << "RESOURCE_COUNT 1" << std::endl;
str << Base::tabs(1) << "RESOURCE 0 {" << std::endl;
str << Base::tabs(2) << "RESOURCE_NAME \"" << resource << "\"" << std::endl;
str << Base::tabs(2) << "MODEL_TYPE \"MESH\"" << std::endl;
str << Base::tabs(2) << "MESH {" << std::endl;
str << Base::tabs(3) << "FACE_COUNT " << fts.size() << std::endl;
str << Base::tabs(3) << "MODEL_POSITION_COUNT " << pts.size() << std::endl;
str << Base::tabs(3) << "MODEL_NORMAL_COUNT " << 3*fts.size() << std::endl;
str << Base::tabs(3) << "MODEL_DIFFUSE_COLOR_COUNT 0" << std::endl;
str << Base::tabs(3) << "MODEL_SPECULAR_COLOR_COUNT 0" << std::endl;
str << Base::tabs(3) << "MODEL_TEXTURE_COORD_COUNT 0" << std::endl;
str << Base::tabs(3) << "MODEL_BONE_COUNT 0" << std::endl;
str << Base::tabs(3) << "MODEL_SHADING_COUNT 1" << std::endl;
str << Base::tabs(3) << "MODEL_SHADING_DESCRIPTION_LIST {" << std::endl;
str << Base::tabs(4) << "SHADING_DESCRIPTION 0 {" << std::endl;
str << Base::tabs(5) << "TEXTURE_LAYER_COUNT 0" << std::endl;
str << Base::tabs(5) << "SHADER_ID 0" << std::endl;
str << Base::tabs(4) << "}" << std::endl;
str << Base::tabs(3) << "}" << std::endl;
str << Base::tabs(3) << "MESH_FACE_POSITION_LIST {" << std::endl;
for (MeshFacetArray::_TConstIterator it = fts.begin(); it != fts.end(); ++it) {
str << Base::tabs(4) << it->_aulPoints[0] << " " << it->_aulPoints[1] << " " << it->_aulPoints[2] << std::endl;
}
str << Base::tabs(3) << "}" << std::endl;
str << Base::tabs(3) << "MESH_FACE_NORMAL_LIST {" << std::endl;
int index = 0;
for (MeshFacetArray::_TConstIterator it = fts.begin(); it != fts.end(); ++it) {
str << Base::tabs(4) << index << " " << index + 1 << " " << index + 2 << std::endl;
index += 3;
}
str << Base::tabs(3) << "}" << std::endl;
str << Base::tabs(3) << "MESH_FACE_SHADING_LIST {" << std::endl;
for (MeshFacetArray::_TConstIterator it = fts.begin(); it != fts.end(); ++it) {
str << Base::tabs(4) << "0" << std::endl;
}
str << Base::tabs(3) << "}" << std::endl;
str << Base::tabs(3) << "MODEL_POSITION_LIST {" << std::endl;
for (MeshPointArray::_TConstIterator it = pts.begin(); it != pts.end(); ++it) {
str << Base::tabs(4) << it->x << " " << it->y << " " << it->z << std::endl;
}
str << Base::tabs(3) << "}" << std::endl;
str << Base::tabs(3) << "MODEL_NORMAL_LIST {" << std::endl;
for (MeshFacetArray::_TConstIterator it = fts.begin(); it != fts.end(); ++it) {
MeshGeomFacet face = _rclMesh.GetFacet(*it);
Base::Vector3f normal = face.GetNormal();
str << Base::tabs(4) << normal.x << " " << normal.y << " " << normal.z << std::endl;
str << Base::tabs(4) << normal.x << " " << normal.y << " " << normal.z << std::endl;
str << Base::tabs(4) << normal.x << " " << normal.y << " " << normal.z << std::endl;
}
str << Base::tabs(3) << "}" << std::endl;
str << Base::tabs(2) << "}" << std::endl;
str << Base::tabs(1) << "}" << std::endl;
str << Base::tabs(0) << "}" << std::endl;
return true;
}
/** Writes an MGL file. */
bool MeshOutput::SaveMGL (std::ostream &str) const
{
/*
light on
list t 0 1 2 | 0 1 3 | 0 2 3 | 1 2 3
list xt 1 1 0 0
list yt -1 -1 1 0
list zt -1 -1 -1 1
triplot t xt yt zt 'b'
#triplot t xt yt zt '#k'
*/
if ((!str) || (str.bad() == true) || (_rclMesh.CountFacets() == 0))
return false;
const MeshPointArray& pts = _rclMesh.GetPoints();
const MeshFacetArray& fts = _rclMesh.GetFacets();
str.precision(2);
str.setf(std::ios::fixed | std::ios::showpoint);
str << "light on" << std::endl;
str << "list t ";
for (MeshFacetArray::_TConstIterator it = fts.begin(); it != fts.end(); ++it) {
str << it->_aulPoints[0] << " " << it->_aulPoints[1] << " " << it->_aulPoints[2] << " | ";
}
str << std::endl;
str << "list xt ";
for (MeshPointArray::_TConstIterator it = pts.begin(); it != pts.end(); ++it) {
str << it->x << " ";
}
str << std::endl;
str << "list yt ";
for (MeshPointArray::_TConstIterator it = pts.begin(); it != pts.end(); ++it) {
str << it->y << " ";
}
str << std::endl;
str << "list zt ";
for (MeshPointArray::_TConstIterator it = pts.begin(); it != pts.end(); ++it) {
str << it->z << " ";
}
str << std::endl;
str << "triplot t xt yt zt 'b'" << std::endl;
str << "#triplot t xt yt zt '#k'" << std::endl;
return true;
}
/** Writes an OpenInventor file. */
bool MeshOutput::SaveInventor (std::ostream &rstrOut) const
{

View File

@@ -46,6 +46,8 @@ namespace MeshIO {
BSTL,
OBJ,
OFF,
IDTF,
MGL,
IV,
X3D,
VRML,
@@ -178,6 +180,10 @@ public:
void SaveXML (Base::Writer &writer) const;
/** Saves a node to an OpenInventor file. */
bool SaveMeshNode (std::ostream &rstrIn);
/** Writes an IDTF file. */
bool SaveIDTF (std::ostream &rstrOut) const;
/** Writes an MGL file. */
bool SaveMGL (std::ostream &rstrOut) const;
/** Writes an OpenInventor file. */
bool SaveInventor (std::ostream &rstrOut) const;
/** Writes an X3D file. */

View File

@@ -122,6 +122,8 @@ private:
{
fcounter[0] = 0;
fcounter[1] = 0;
facet[0] = 0;
facet[1] = 0;
}
};

View File

@@ -91,20 +91,20 @@ App::DocumentObjectExecReturn *SetOperations::execute(void)
else if (ot == "outer")
type = MeshCore::SetOperations::Outer;
else
throw new Base::ValueError("Operation type must either be 'union' or 'intersection'"
" or 'difference' or 'inner' or 'outer'");
throw Base::ValueError("Operation type must either be 'union' or 'intersection'"
" or 'difference' or 'inner' or 'outer'");
MeshCore::SetOperations setOp(meshKernel1.getKernel(), meshKernel2.getKernel(),
pcKernel->getKernel(), type, 1.0e-5f);
setOp.Do();
Mesh.setValuePtr(pcKernel.release());
}
else {
else {
// Error mesh property
if (!mesh1)
throw new Base::ValueError("First input mesh not set");
throw Base::ValueError("First input mesh not set");
if (!mesh2)
throw new Base::ValueError("Second input mesh not set");
throw Base::ValueError("Second input mesh not set");
}
return App::DocumentObject::StdReturn;

View File

@@ -596,12 +596,16 @@ void MeshObject::addMesh(const MeshCore::MeshKernel& kernel)
void MeshObject::deleteFacets(const std::vector<unsigned long>& removeIndices)
{
if (removeIndices.empty())
return;
_kernel.DeleteFacets(removeIndices);
deletedFacets(removeIndices);
}
void MeshObject::deletePoints(const std::vector<unsigned long>& removeIndices)
{
if (removeIndices.empty())
return;
_kernel.DeletePoints(removeIndices);
this->_segments.clear();
}

View File

@@ -405,7 +405,8 @@ The argument int is the mode: 0=inner, 1=outer
</Methode>
<Methode Name="smooth" Const="true">
<Documentation>
<UserDocu>Smooth the mesh</UserDocu>
<UserDocu>Smooth the mesh
smooth([iteration=1,maxError=FLT_MAX])</UserDocu>
</Documentation>
</Methode>
<Methode Name="optimizeTopology" Const="true">

View File

@@ -212,6 +212,8 @@ PyObject* MeshPy::write(PyObject *args, PyObject *kwds)
ext["AST" ] = MeshCore::MeshIO::ASTL;
ext["OBJ" ] = MeshCore::MeshIO::OBJ;
ext["OFF" ] = MeshCore::MeshIO::OFF;
ext["IDTF"] = MeshCore::MeshIO::IDTF;
ext["MGL" ] = MeshCore::MeshIO::MGL;
ext["IV" ] = MeshCore::MeshIO::IV;
ext["X3D" ] = MeshCore::MeshIO::X3D;
ext["VRML"] = MeshCore::MeshIO::VRML;

View File

@@ -7,6 +7,12 @@ include_directories(
${XercesC_INCLUDE_DIRS}
)
if(MSVC)
include_directories(
${CMAKE_SOURCE_DIR}/src/3rdParty/OpenGL/api
)
endif(MSVC)
set(MeshGui_LIBS
${Boost_LIBRARIES}
${OPENGL_glu_LIBRARY}

View File

@@ -37,10 +37,14 @@
# include <Inventor/elements/SoCoordinateElement.h>
# include <Inventor/elements/SoGLCoordinateElement.h>
# include <Inventor/elements/SoMaterialBindingElement.h>
# include <Inventor/elements/SoNormalBindingElement.h>
# include <Inventor/elements/SoProjectionMatrixElement.h>
# include <Inventor/elements/SoViewingMatrixElement.h>
#endif
#include <GL/glext.h>
#include <Inventor/C/glue/gl.h>
#include <Gui/SoFCInteractiveElement.h>
#include <Gui/SoFCSelectionAction.h>
#include "SoFCIndexedFaceSet.h"
@@ -48,6 +52,8 @@
using namespace MeshGui;
//#define RENDER_GLARRAYS
SO_NODE_SOURCE(SoFCIndexedFaceSet);
void SoFCIndexedFaceSet::initClass()
@@ -55,7 +61,7 @@ void SoFCIndexedFaceSet::initClass()
SO_NODE_INIT_CLASS(SoFCIndexedFaceSet, SoIndexedFaceSet, "IndexedFaceSet");
}
SoFCIndexedFaceSet::SoFCIndexedFaceSet() : renderTriangleLimit(100000), selectBuf(0)
SoFCIndexedFaceSet::SoFCIndexedFaceSet() : renderTriangleLimit(100000), updateGLArray(false), selectBuf(0)
{
SO_NODE_CONSTRUCTOR(SoFCIndexedFaceSet);
setName(SoFCIndexedFaceSet::getClassTypeId().getName());
@@ -77,9 +83,32 @@ void SoFCIndexedFaceSet::GLRender(SoGLRenderAction *action)
unsigned int num = this->coordIndex.getNum()/4;
if (mode == false || num <= this->renderTriangleLimit) {
#ifdef RENDER_GLARRAYS
SoMaterialBindingElement::Binding matbind =
SoMaterialBindingElement::get(state);
if (matbind == SoMaterialBindingElement::OVERALL) {
SoMaterialBundle mb(action);
mb.sendFirst();
if (updateGLArray) {
updateGLArray = false;
generateGLArrays(state);
}
renderFacesGLArray(action);
}
else {
inherited::GLRender(action);
}
#else
inherited::GLRender(action);
#endif
}
else {
#if 0 && defined (RENDER_GLARRAYS)
SoMaterialBundle mb(action);
mb.sendFirst();
renderCoordsGLArray(action);
#else
SoMaterialBindingElement::Binding matbind =
SoMaterialBindingElement::get(state);
int32_t binding = (int32_t)(matbind);
@@ -108,6 +137,7 @@ void SoFCIndexedFaceSet::GLRender(SoGLRenderAction *action)
normals, nindices, &mb, mindices, binding, &tb, tindices);
// Disable caching for this node
SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DONT_AUTO_CACHE);
#endif
}
}
@@ -189,6 +219,144 @@ void SoFCIndexedFaceSet::drawCoords(const SoGLCoordinateElement * const vertexli
glEnd();
}
void SoFCIndexedFaceSet::invalidate()
{
updateGLArray = true;
}
void SoFCIndexedFaceSet::generateGLArrays(SoState * state)
{
this->index_array.resize(0);
this->vertex_array.resize(0);
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 normalCacheUsed;
SbBool sendNormals = true;
this->getVertexData(state, coords, normals, cindices,
nindices, tindices, mindices, numindices,
sendNormals, normalCacheUsed);
const SbVec3f * points = coords->getArrayPtr3();
std::vector<float> face_vertices;
std::vector<int32_t> face_indices;
std::size_t numTria = numindices / 4;
SoNormalBindingElement::Binding normbind = SoNormalBindingElement::get(state);
if (normbind == SoNormalBindingElement::PER_VERTEX_INDEXED) {
face_vertices.reserve(3 * numTria * 6); // duplicate each vertex
face_indices.resize(3 * numTria);
// the nindices must have the length of numindices
int32_t vertex = 0;
int index = 0;
for (std::size_t i=0; i<numTria; i++) {
for (int j=0; j<3; j++) {
const SbVec3f& n = normals[nindices[index]];
face_vertices.push_back(n[0]);
face_vertices.push_back(n[1]);
face_vertices.push_back(n[2]);
const SbVec3f& p = points[cindices[index]];
face_vertices.push_back(p[0]);
face_vertices.push_back(p[1]);
face_vertices.push_back(p[2]);
face_indices[vertex] = vertex;
vertex++;
index++;
}
index++;
}
}
this->index_array.swap(face_indices);
this->vertex_array.swap(face_vertices);
}
//****************************************************************************
// renderFacesGLArray: normal and coord from vertex_array;
// no texture, color, highlight or selection but highest possible speed;
// all vertices written in one go!
//
// Benchmark tests with an 256 MB STL file:
//
// Implementation | FPS
// ================================================
// OpenInventor | 3.5
// With GL_PRIMITIVE_RESTART | 0.9
// With GL_PRIMITIVE_RESTART_FIXED_INDEX | 0.9
// Without GL_PRIMITIVE_RESTART | 12.5
//
void SoFCIndexedFaceSet::renderFacesGLArray(SoGLRenderAction *action)
{
#if 0 // use Inventor's coordIndex saves memory but the rendering is very slow then
const cc_glglue * glue = cc_glglue_instance(action->getCacheContext());
PFNGLPRIMITIVERESTARTINDEXPROC glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC)
cc_glglue_getprocaddress(glue, "glPrimitiveRestartIndex");
int cnt = coordIndex.getNum();
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
// https://www.opengl.org/discussion_boards/archive/index.php/t-180767.html
// https://www.khronos.org/opengl/wiki/Vertex_Rendering#Primitive_Restart
glPrimitiveRestartIndex(0xffffffff);
glEnable(GL_PRIMITIVE_RESTART);
//glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
glInterleavedArrays(GL_N3F_V3F, 0, &(vertex_array[0]));
glDrawElements(GL_TRIANGLES, cnt, GL_UNSIGNED_INT, coordIndex.getValues(0));
glDisable(GL_PRIMITIVE_RESTART);
//glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
#else // Needs more memory but makes it very fast
(void)action;
int cnt = index_array.size();
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glInterleavedArrays(GL_N3F_V3F, 0, &(vertex_array[0]));
glDrawElements(GL_TRIANGLES, cnt, GL_UNSIGNED_INT, &(index_array[0]));
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
#endif
}
// Implementation | FPS
// ================================================
// drawCoords (every 4th vertex) | 20.0
// renderCoordsGLArray (all vertexes) | 20.0
//
void SoFCIndexedFaceSet::renderCoordsGLArray(SoGLRenderAction *action)
{
(void)action;
int cnt = index_array.size();
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glInterleavedArrays(GL_N3F_V3F, 0, &(vertex_array[0]));
glDrawElements(GL_POINTS, cnt, GL_UNSIGNED_INT, &(index_array[0]));
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
}
void SoFCIndexedFaceSet::doAction(SoAction * action)
{
if (action->getTypeId() == Gui::SoGLSelectAction::getClassTypeId()) {

View File

@@ -23,7 +23,6 @@
#ifndef MESHGUI_SOFCINDEXEDFACESET_H
#define MESHGUI_SOFCINDEXEDFACESET_H
#include <Inventor/nodes/SoIndexedFaceSet.h>
class SoGLCoordinateElement;
@@ -53,6 +52,8 @@ public:
unsigned int renderTriangleLimit;
void invalidate();
protected:
// Force using the reference count mechanism.
virtual ~SoFCIndexedFaceSet() {}
@@ -78,6 +79,14 @@ private:
void stopVisibility(SoAction * action);
void renderVisibleFaces(const SbVec3f *);
void generateGLArrays(SoState * state);
void renderFacesGLArray(SoGLRenderAction *action);
void renderCoordsGLArray(SoGLRenderAction *action);
private:
std::vector<int32_t> index_array;
std::vector<float> vertex_array;
SbBool updateGLArray;
GLuint *selectBuf;
};

View File

@@ -590,19 +590,25 @@ void SoFCMeshObjectShape::initClass()
SoFCMeshObjectShape::SoFCMeshObjectShape()
: renderTriangleLimit(100000)
, meshChanged(true)
, selectBuf(0)
, updateGLArray(false)
{
SO_NODE_CONSTRUCTOR(SoFCMeshObjectShape);
setName(SoFCMeshObjectShape::getClassTypeId().getName());
}
SoFCMeshObjectShape::~SoFCMeshObjectShape()
{
}
void SoFCMeshObjectShape::notify(SoNotList * node)
{
inherited::notify(node);
meshChanged = true;
updateGLArray = true;
}
#define RENDER_GLARRAYS
/**
* Either renders the complete mesh or only a subset of the points.
*/
@@ -634,13 +640,27 @@ void SoFCMeshObjectShape::GLRender(SoGLRenderAction *action)
ccw = false;
if (mode == false || mesh->countFacets() <= this->renderTriangleLimit) {
if (mbind != OVERALL)
if (mbind != OVERALL) {
drawFaces(mesh, &mb, mbind, needNormals, ccw);
else
}
else {
#ifdef RENDER_GLARRAYS
if (updateGLArray) {
updateGLArray = false;
generateGLArrays(state);
}
renderFacesGLArray(action);
#else
drawFaces(mesh, 0, mbind, needNormals, ccw);
#endif
}
}
else {
#if 0 && defined (RENDER_GLARRAYS)
renderCoordsGLArray(action);
#else
drawPoints(mesh, needNormals, ccw);
#endif
}
// Disable caching for this node
@@ -845,6 +865,102 @@ void SoFCMeshObjectShape::drawPoints(const Mesh::MeshObject * mesh, SbBool needN
}
}
void SoFCMeshObjectShape::generateGLArrays(SoState * state)
{
const Mesh::MeshObject * mesh = SoFCMeshObjectElement::get(state);
this->index_array.resize(0);
this->vertex_array.resize(0);
std::vector<float> face_vertices;
std::vector<int32_t> face_indices;
const MeshCore::MeshKernel& kernel = mesh->getKernel();
const MeshCore::MeshPointArray& cP = kernel.GetPoints();
const MeshCore::MeshFacetArray& cF = kernel.GetFacets();
#if 0
// Smooth shading
face_vertices.resize(cP.size() * 6);
face_indices.resize(3 * cF.size());
int indexed = 0;
for (MeshCore::MeshPointArray::const_iterator it = cP.begin(); it != cP.end(); ++it) {
face_vertices[indexed * 6 + 3] += it->x;
face_vertices[indexed * 6 + 4] += it->y;
face_vertices[indexed * 6 + 5] += it->z;
indexed++;
}
indexed = 0;
for (MeshCore::MeshFacetArray::const_iterator it = cF.begin(); it != cF.end(); ++it) {
Base::Vector3f n = kernel.GetFacet(*it).GetNormal();
for (int i=0; i<3; i++) {
int32_t idx = it->_aulPoints[i];
face_vertices[idx * 6 + 0] += n.x;
face_vertices[idx * 6 + 1] += n.y;
face_vertices[idx * 6 + 2] += n.z;
face_indices[indexed++] = idx;
}
}
#else
// Flat shading
face_vertices.reserve(3 * cF.size() * 6); // duplicate each vertex
face_indices.resize(3 * cF.size());
int indexed = 0;
for (MeshCore::MeshFacetArray::const_iterator it = cF.begin(); it != cF.end(); ++it) {
Base::Vector3f n = kernel.GetFacet(*it).GetNormal();
for (int i=0; i<3; i++) {
face_vertices.push_back(n.x);
face_vertices.push_back(n.y);
face_vertices.push_back(n.z);
const Base::Vector3f& v = cP[it->_aulPoints[i]];
face_vertices.push_back(v.x);
face_vertices.push_back(v.y);
face_vertices.push_back(v.z);
face_indices[indexed] = indexed;
indexed++;
}
}
#endif
this->index_array.swap(face_indices);
this->vertex_array.swap(face_vertices);
}
void SoFCMeshObjectShape::renderFacesGLArray(SoGLRenderAction *action)
{
(void)action;
GLsizei cnt = static_cast<GLsizei>(index_array.size());
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glInterleavedArrays(GL_N3F_V3F, 0, &(vertex_array[0]));
glDrawElements(GL_TRIANGLES, cnt, GL_UNSIGNED_INT, &(index_array[0]));
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
}
void SoFCMeshObjectShape::renderCoordsGLArray(SoGLRenderAction *action)
{
(void)action;
int cnt = index_array.size();
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glInterleavedArrays(GL_N3F_V3F, 0, &(vertex_array[0]));
glDrawElements(GL_POINTS, cnt, GL_UNSIGNED_INT, &(index_array[0]));
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
}
void SoFCMeshObjectShape::doAction(SoAction * action)
{
if (action->getTypeId() == Gui::SoGLSelectAction::getClassTypeId()) {

View File

@@ -194,7 +194,7 @@ private:
private:
// Force using the reference count mechanism.
virtual ~SoFCMeshObjectShape() {};
virtual ~SoFCMeshObjectShape();
virtual void notify(SoNotList * list);
Binding findMaterialBinding(SoState * const state) const;
// Draw faces
@@ -207,11 +207,18 @@ private:
void stopSelection(SoAction * action, const Mesh::MeshObject*);
void renderSelectionGeometry(const Mesh::MeshObject*);
void generateGLArrays(SoState * state);
void renderFacesGLArray(SoGLRenderAction *action);
void renderCoordsGLArray(SoGLRenderAction *action);
private:
bool meshChanged;
GLuint *selectBuf;
GLfloat modelview[16];
GLfloat projection[16];
// Vertex array handling
std::vector<int32_t> index_array;
std::vector<float> vertex_array;
SbBool updateGLArray;
};
class MeshGuiExport SoFCMeshSegmentShape : public SoShape {

View File

@@ -143,6 +143,7 @@ void ViewProviderMeshFaceSet::updateData(const App::Property* prop)
else {
ViewProviderMeshBuilder builder;
builder.createMesh(prop, pcMeshCoord, pcMeshFaces);
pcMeshFaces->invalidate();
}
if (direct != directRendering) {

View File

@@ -26,6 +26,7 @@
#include <Mod/Mesh/Gui/ViewProvider.h>
namespace MeshGui {
class SoFCIndexedFaceSet;
/**
* The ViewProviderMeshFaceSet class creates nodes for representing the mesh
@@ -65,7 +66,7 @@ private:
bool directRendering;
unsigned long triangleCount;
SoCoordinate3 * pcMeshCoord;
SoIndexedFaceSet * pcMeshFaces;
SoFCIndexedFaceSet * pcMeshFaces;
SoFCMeshObjectNode * pcMeshNode;
SoFCMeshObjectShape * pcMeshShape;
};