Mesh: Refactor MeshOutput::SaveInventor
This commit is contained in:
@@ -104,6 +104,8 @@ SET(Core_SRCS
|
||||
Core/IO/ReaderOBJ.h
|
||||
Core/IO/Writer3MF.cpp
|
||||
Core/IO/Writer3MF.h
|
||||
Core/IO/WriterInventor.cpp
|
||||
Core/IO/WriterInventor.h
|
||||
Core/IO/WriterOBJ.cpp
|
||||
Core/IO/WriterOBJ.h
|
||||
)
|
||||
|
||||
221
src/Mod/Mesh/App/Core/IO/WriterInventor.cpp
Normal file
221
src/Mod/Mesh/App/Core/IO/WriterInventor.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2022 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"
|
||||
|
||||
#include <Base/Builder3D.h>
|
||||
#include <Base/Placement.h>
|
||||
#include "Core/Iterator.h"
|
||||
|
||||
#include "WriterInventor.h"
|
||||
|
||||
|
||||
using namespace MeshCore;
|
||||
|
||||
class WriterInventorImp
|
||||
{
|
||||
Base::InventorBuilder& builder;
|
||||
|
||||
public:
|
||||
static bool isStreamInvalid(std::ostream& out)
|
||||
{
|
||||
return !out || out.bad();
|
||||
}
|
||||
|
||||
WriterInventorImp(Base::InventorBuilder& builder)
|
||||
: builder(builder)
|
||||
{
|
||||
}
|
||||
|
||||
void setupStream(std::ostream& out)
|
||||
{
|
||||
out.precision(6);
|
||||
out.setf(std::ios::fixed | std::ios::showpoint);
|
||||
}
|
||||
|
||||
void addInfoNode()
|
||||
{
|
||||
Base::InfoItem info{"Created by FreeCAD <https://www.freecadweb.org>"};
|
||||
builder.addNode(info);
|
||||
}
|
||||
|
||||
void addLabel(const MeshCore::MeshKernel& kernel)
|
||||
{
|
||||
std::stringstream str;
|
||||
str << "Triangle mesh contains "
|
||||
<< kernel.CountPoints()
|
||||
<< " vertices and "
|
||||
<< kernel.CountFacets()
|
||||
<< " faces";
|
||||
Base::LabelItem label{str.str().c_str()};
|
||||
builder.addNode(label);
|
||||
}
|
||||
|
||||
void addTransformNode(const Base::Matrix4D& mat, bool append)
|
||||
{
|
||||
if (!append)
|
||||
return;
|
||||
|
||||
Base::Placement placement;
|
||||
placement.fromMatrix(mat);
|
||||
|
||||
Base::TransformItem item{placement};
|
||||
builder.addNode(item);
|
||||
}
|
||||
|
||||
void addNormalNode(const MeshCore::MeshKernel& kernel)
|
||||
{
|
||||
MeshFacetIterator clIter(kernel), clEnd(kernel);
|
||||
const MeshGeomFacet* geomFacet = nullptr;
|
||||
|
||||
// write out the normals of the facets
|
||||
std::vector<Base::Vector3f> normals;
|
||||
normals.reserve(kernel.CountFacets());
|
||||
|
||||
clIter.Begin();
|
||||
clEnd.End();
|
||||
|
||||
while (clIter < clEnd) {
|
||||
geomFacet = &(*clIter);
|
||||
normals.push_back(geomFacet->GetNormal());
|
||||
++clIter;
|
||||
}
|
||||
|
||||
builder.addNode(Base::NormalItem{normals});
|
||||
|
||||
Base::NormalBindingItem binding;
|
||||
binding.setValue(Base::BindingElement::Binding::PerFace);
|
||||
builder.addNode(binding);
|
||||
}
|
||||
|
||||
void addCoordinateNode(const MeshCore::MeshKernel& kernel)
|
||||
{
|
||||
const MeshPointArray& points = kernel.GetPoints();
|
||||
|
||||
// coordinates of the vertices
|
||||
std::vector<Base::Vector3f> coords;
|
||||
coords.reserve(points.size());
|
||||
coords.insert(coords.begin(), points.begin(), points.end());
|
||||
|
||||
builder.addNode(Base::Coordinate3Item{coords});
|
||||
}
|
||||
|
||||
void addMaterialNode(const Material* material)
|
||||
{
|
||||
if (!material)
|
||||
return;
|
||||
|
||||
auto transformColors = [](const std::vector<App::Color>& input) {
|
||||
std::vector<Base::ColorRGB> output;
|
||||
output.reserve(input.size());
|
||||
std::transform(input.cbegin(), input.cend(), std::back_inserter(output), [](const App::Color& col) {
|
||||
return Base::ColorRGB{col.r, col.g, col.b};
|
||||
});
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
Base::MaterialItem mat;
|
||||
mat.setAmbientColor(transformColors(material->ambientColor));
|
||||
mat.setDiffuseColor(transformColors(material->diffuseColor));
|
||||
mat.setSpecularColor(transformColors(material->specularColor));
|
||||
mat.setEmissiveColor(transformColors(material->emissiveColor));
|
||||
mat.setShininess(material->shininess);
|
||||
mat.setTransparency(material->transparency);
|
||||
builder.addNode(mat);
|
||||
}
|
||||
|
||||
void addMaterialBindingNode(const Material* material)
|
||||
{
|
||||
if (!material)
|
||||
return;
|
||||
|
||||
Base::MaterialBindingItem binding;
|
||||
switch (material->binding) {
|
||||
case MeshIO::PER_FACE:
|
||||
binding.setValue(Base::BindingElement::Binding::PerFace);
|
||||
break;
|
||||
case MeshIO::PER_VERTEX:
|
||||
binding.setValue(Base::BindingElement::Binding::PerVertex);
|
||||
break;
|
||||
default:
|
||||
binding.setValue(Base::BindingElement::Binding::Overall);
|
||||
break;
|
||||
}
|
||||
|
||||
builder.addNode(binding);
|
||||
}
|
||||
|
||||
void addIndexedFaceSetNode(const MeshCore::MeshKernel& kernel)
|
||||
{
|
||||
// and finally the facets with their point indices
|
||||
const MeshFacetArray& faces = kernel.GetFacets();
|
||||
std::vector<int> indices;
|
||||
indices.reserve(4 * faces.size());
|
||||
for (const auto& it : faces) {
|
||||
indices.push_back(static_cast<int>(it._aulPoints[0]));
|
||||
indices.push_back(static_cast<int>(it._aulPoints[1]));
|
||||
indices.push_back(static_cast<int>(it._aulPoints[2]));
|
||||
indices.push_back(-1);
|
||||
}
|
||||
|
||||
builder.addNode(Base::IndexedFaceSetItem{indices});
|
||||
}
|
||||
};
|
||||
|
||||
WriterInventor::WriterInventor(const MeshKernel& kernel, const Material* material)
|
||||
: _kernel(kernel)
|
||||
, _material(material)
|
||||
, apply_transform(false)
|
||||
{
|
||||
}
|
||||
|
||||
void WriterInventor::SetTransform(const Base::Matrix4D& mat)
|
||||
{
|
||||
_transform = mat;
|
||||
if (mat != Base::Matrix4D())
|
||||
apply_transform = true;
|
||||
}
|
||||
|
||||
bool WriterInventor::Save(std::ostream& out)
|
||||
{
|
||||
if (WriterInventorImp::isStreamInvalid(out))
|
||||
return false;
|
||||
|
||||
Base::InventorBuilder builder(out);
|
||||
builder.beginSeparator();
|
||||
|
||||
WriterInventorImp writer{builder};
|
||||
writer.setupStream(out);
|
||||
writer.addInfoNode();
|
||||
writer.addLabel(_kernel);
|
||||
writer.addTransformNode(_transform, apply_transform);
|
||||
writer.addNormalNode(_kernel);
|
||||
writer.addCoordinateNode(_kernel);
|
||||
writer.addMaterialNode(_material);
|
||||
writer.addMaterialBindingNode(_material);
|
||||
writer.addIndexedFaceSetNode(_kernel);
|
||||
|
||||
builder.endSeparator();
|
||||
|
||||
return true;
|
||||
}
|
||||
61
src/Mod/Mesh/App/Core/IO/WriterInventor.h
Normal file
61
src/Mod/Mesh/App/Core/IO/WriterInventor.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2022 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 MESH_IO_WRITER_IV_H
|
||||
#define MESH_IO_WRITER_IV_H
|
||||
|
||||
#include <Mod/Mesh/MeshGlobal.h>
|
||||
#include <Mod/Mesh/App/Core/MeshIO.h>
|
||||
|
||||
namespace MeshCore
|
||||
{
|
||||
|
||||
/** Saves the mesh object into OpenInventor v2.1 format. */
|
||||
class MeshExport WriterInventor
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* \brief WriterInventor
|
||||
*/
|
||||
explicit WriterInventor(const MeshKernel& kernel, const Material*);
|
||||
/*!
|
||||
* \brief Apply a transformation for the exported mesh.
|
||||
*/
|
||||
void SetTransform(const Base::Matrix4D&);
|
||||
/*!
|
||||
* \brief Save the mesh to an OpenInventor file.
|
||||
* \return true if the data could be written successfully, false otherwise.
|
||||
*/
|
||||
bool Save(std::ostream&);
|
||||
|
||||
private:
|
||||
const MeshKernel& _kernel;
|
||||
const Material* _material;
|
||||
Base::Matrix4D _transform;
|
||||
bool apply_transform;
|
||||
};
|
||||
|
||||
} // namespace MeshCore
|
||||
|
||||
|
||||
#endif // MESH_IO_WRITER_IV_H
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "IO/Reader3MF.h"
|
||||
#include "IO/ReaderOBJ.h"
|
||||
#include "IO/Writer3MF.h"
|
||||
#include "IO/WriterInventor.h"
|
||||
#include "IO/WriterOBJ.h"
|
||||
#include <zipios++/gzipoutputstream.h>
|
||||
#include <zipios++/zipoutputstream.h>
|
||||
@@ -2671,83 +2672,9 @@ triplot t xt yt zt 'b'
|
||||
/** Writes an OpenInventor file. */
|
||||
bool MeshOutput::SaveInventor (std::ostream &rstrOut) const
|
||||
{
|
||||
if (!rstrOut || rstrOut.bad() || (_rclMesh.CountFacets() == 0))
|
||||
return false;
|
||||
|
||||
MeshFacetIterator clIter(_rclMesh), clEnd(_rclMesh);
|
||||
clIter.Transform(this->_transform);
|
||||
MeshPointIterator clPtIter(_rclMesh), clPtEnd(_rclMesh);
|
||||
clPtIter.Transform(this->_transform);
|
||||
const MeshGeomFacet* pclFacet;
|
||||
|
||||
Base::SequencerLauncher seq("Saving...", _rclMesh.CountFacets() + 1);
|
||||
rstrOut.precision(6);
|
||||
rstrOut.setf(std::ios::fixed | std::ios::showpoint);
|
||||
|
||||
// Header info
|
||||
Base::InventorBuilder builder(rstrOut);
|
||||
builder.beginSeparator();
|
||||
Base::InfoItem info{"Created by FreeCAD <http://www.freecadweb.org>"};
|
||||
builder.addNode(info);
|
||||
std::stringstream str;
|
||||
str << "Triangle mesh contains "
|
||||
<< _rclMesh.CountPoints()
|
||||
<< " vertices and "
|
||||
<< _rclMesh.CountFacets()
|
||||
<< " faces";
|
||||
Base::LabelItem label{str.str().c_str()};
|
||||
builder.addNode(label);
|
||||
|
||||
// write out the normals of the facets
|
||||
std::vector<Base::Vector3f> normals;
|
||||
normals.reserve(_rclMesh.CountFacets());
|
||||
|
||||
clIter.Begin();
|
||||
clEnd.End();
|
||||
|
||||
while (clIter < clEnd) {
|
||||
pclFacet = &(*clIter);
|
||||
normals.push_back(pclFacet->GetNormal());
|
||||
++clIter;
|
||||
|
||||
seq.next(true); // allow to cancel
|
||||
}
|
||||
|
||||
builder.addNode(Base::NormalItem{normals});
|
||||
|
||||
Base::NormalBindingItem binding;
|
||||
binding.setValue(Base::BindingElement::Binding::PerFace);
|
||||
builder.addNode(binding);
|
||||
|
||||
// coordinates of the vertices
|
||||
std::vector<Base::Vector3f> coords;
|
||||
coords.reserve(_rclMesh.CountPoints());
|
||||
|
||||
clPtIter.Begin();
|
||||
clPtEnd.End();
|
||||
|
||||
while (clPtIter < clPtEnd) {
|
||||
coords.push_back(*clPtIter);
|
||||
++clPtIter;
|
||||
seq.next(true); // allow to cancel
|
||||
}
|
||||
|
||||
builder.addNode(Base::Coordinate3Item{coords});
|
||||
|
||||
// and finally the facets with their point indices
|
||||
const MeshFacetArray& faces = _rclMesh.GetFacets();
|
||||
std::vector<int> indices;
|
||||
indices.reserve(4 * faces.size());
|
||||
for (MeshFacetArray::_TConstIterator it = faces.begin(); it != faces.end(); ++it) {
|
||||
indices.push_back(static_cast<int>(it->_aulPoints[0]));
|
||||
indices.push_back(static_cast<int>(it->_aulPoints[1]));
|
||||
indices.push_back(static_cast<int>(it->_aulPoints[2]));
|
||||
indices.push_back(-1);
|
||||
}
|
||||
builder.addNode(Base::IndexedFaceSetItem{indices});
|
||||
builder.endSeparator();
|
||||
|
||||
return true;
|
||||
WriterInventor writer(_rclMesh, _material);
|
||||
writer.SetTransform(_transform);
|
||||
return writer.Save(rstrOut);
|
||||
}
|
||||
|
||||
/** Writes an X3D file. */
|
||||
|
||||
Reference in New Issue
Block a user