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:
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -122,6 +122,8 @@ private:
|
||||
{
|
||||
fcounter[0] = 0;
|
||||
fcounter[1] = 0;
|
||||
facet[0] = 0;
|
||||
facet[1] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -143,6 +143,7 @@ void ViewProviderMeshFaceSet::updateData(const App::Property* prop)
|
||||
else {
|
||||
ViewProviderMeshBuilder builder;
|
||||
builder.createMesh(prop, pcMeshCoord, pcMeshFaces);
|
||||
pcMeshFaces->invalidate();
|
||||
}
|
||||
|
||||
if (direct != directRendering) {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user