Mesh: add support of thumbnails of 3MF format
This commit is contained in:
@@ -76,6 +76,11 @@ bool Writer3MF::AddMesh(const MeshKernel& mesh, const Base::Matrix4D& mat)
|
||||
return SaveObject(zip, id, mesh);
|
||||
}
|
||||
|
||||
void Writer3MF::AddResource(const Resource3MF& res)
|
||||
{
|
||||
resources.emplace_back(res);
|
||||
}
|
||||
|
||||
bool Writer3MF::Save()
|
||||
{
|
||||
Finish(zip);
|
||||
@@ -90,6 +95,12 @@ bool Writer3MF::Save()
|
||||
if (!SaveContent(zip))
|
||||
return false;
|
||||
zip.closeEntry();
|
||||
for (const auto& it : resources) {
|
||||
zip.putNextEntry(it.fileNameInZip);
|
||||
zip.write(it.fileContent.data(), it.fileContent.size());
|
||||
zip.closeEntry();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -163,19 +174,24 @@ std::string Writer3MF::DumpMatrix(const Base::Matrix4D& mat) const
|
||||
|
||||
bool Writer3MF::SaveRels(std::ostream &str) const
|
||||
{
|
||||
int ids = 1;
|
||||
str << "<?xml version='1.0' encoding='UTF-8'?>\n"
|
||||
<< "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">"
|
||||
"<Relationship Id=\"rel0\" Target=\"/3D/3dmodel.model\" Type=\"http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel\" />"
|
||||
"</Relationships>";
|
||||
<< "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n"
|
||||
<< " <Relationship Target=\"/3D/3dmodel.model\" Id=\"rel0\" Type=\"http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel\" />\n";
|
||||
for (const auto& it : resources)
|
||||
str << " <Relationship Target=\"" << it.relationshipTarget << "\" Id=\"rel" << ++ids << "\" Type=\"" << it.relationshipType << "\" />\n";
|
||||
str << "</Relationships>\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Writer3MF::SaveContent(std::ostream &str) const
|
||||
{
|
||||
str << "<?xml version='1.0' encoding='UTF-8'?>\n"
|
||||
<< "<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">"
|
||||
"<Default ContentType=\"application/vnd.openxmlformats-package.relationships+xml\" Extension=\"rels\" />"
|
||||
"<Default ContentType=\"application/vnd.ms-package.3dmanufacturing-3dmodel+xml\" Extension=\"model\" />"
|
||||
"</Types>";
|
||||
<< "<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">\n"
|
||||
<< " <Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>\n"
|
||||
<< " <Default Extension=\"model\" ContentType=\"application/vnd.ms-package.3dmanufacturing-3dmodel+xml\"/>\n";
|
||||
for (const auto& it : resources)
|
||||
str << " <Default Extension=\"" << it.extension << "\" ContentType=\"" << it.contentType << "\"/>\n";
|
||||
str << "</Types>";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -25,14 +25,26 @@
|
||||
#define MESH_IO_WRITER_3MF_H
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
#include "Core/Elements.h"
|
||||
#include <zipios++/zipoutputstream.h>
|
||||
#include <Mod/Mesh/MeshGlobal.h>
|
||||
|
||||
namespace Base {
|
||||
class Matrix4D;
|
||||
}
|
||||
|
||||
namespace MeshCore
|
||||
{
|
||||
class MeshKernel;
|
||||
|
||||
struct Resource3MF {
|
||||
std::string extension;
|
||||
std::string contentType;
|
||||
std::string relationshipTarget;
|
||||
std::string relationshipType;
|
||||
std::string fileNameInZip;
|
||||
std::string fileContent;
|
||||
};
|
||||
|
||||
/** Saves the mesh object into 3MF format. */
|
||||
class MeshExport Writer3MF
|
||||
{
|
||||
@@ -58,6 +70,11 @@ public:
|
||||
* \return true if the added mesh could be written successfully, false otherwise.
|
||||
*/
|
||||
bool AddMesh(const MeshKernel& mesh, const Base::Matrix4D& mat);
|
||||
/*!
|
||||
* \brief AddResource
|
||||
* Add an additional resource to the 3MF file.
|
||||
*/
|
||||
void AddResource(const Resource3MF&);
|
||||
/*!
|
||||
* \brief After having added the mesh objects with \ref AddMesh save the meta-information
|
||||
* to the 3MF file.
|
||||
@@ -79,6 +96,7 @@ private:
|
||||
zipios::ZipOutputStream zip;
|
||||
int objectIndex;
|
||||
std::vector<std::string> items;
|
||||
std::vector<Resource3MF> resources;
|
||||
};
|
||||
|
||||
} // namespace MeshCore
|
||||
|
||||
@@ -229,12 +229,29 @@ bool MergeExporter::addMesh(const char *name, const MeshObject & mesh)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void Extension3MFFactory::addProducer(AbstractExtensionProducer* ext)
|
||||
{
|
||||
producer.emplace_back(ext);
|
||||
}
|
||||
|
||||
std::vector<Extension3MFPtr> Extension3MFFactory::create()
|
||||
{
|
||||
std::vector<Extension3MFPtr> ext;
|
||||
for (const auto& it : producer)
|
||||
ext.emplace_back(it->create());
|
||||
return ext;
|
||||
}
|
||||
|
||||
std::vector<AbstractExtensionProducerPtr> Extension3MFFactory::producer;
|
||||
|
||||
class Exporter3MF::Private {
|
||||
public:
|
||||
Private(const std::string& filename)
|
||||
: writer3mf(filename) {
|
||||
ext = Extension3MFFactory::create();
|
||||
}
|
||||
MeshCore::Writer3MF writer3mf;
|
||||
std::vector<Extension3MFPtr> ext;
|
||||
};
|
||||
|
||||
Exporter3MF::Exporter3MF(std::string fileName)
|
||||
@@ -251,7 +268,14 @@ Exporter3MF::~Exporter3MF()
|
||||
bool Exporter3MF::addMesh(const char *name, const MeshObject & mesh)
|
||||
{
|
||||
boost::ignore_unused(name);
|
||||
return d->writer3mf.AddMesh(mesh.getKernel(), mesh.getTransform());
|
||||
bool ok = d->writer3mf.AddMesh(mesh.getKernel(), mesh.getTransform());
|
||||
if (ok) {
|
||||
for (const auto& it : d->ext) {
|
||||
d->writer3mf.AddResource(it->addMesh(mesh));
|
||||
}
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void Exporter3MF::write()
|
||||
@@ -410,7 +434,7 @@ bool ExporterAMF::addMesh(const char *name, const MeshObject & mesh)
|
||||
|
||||
*outputStreamPtr << "\t\t\t</vertices>\n"
|
||||
<< "\t\t\t<volume>\n";
|
||||
|
||||
|
||||
// Now that we've output all the vertices, we can
|
||||
// output the facets that refer to them!
|
||||
for (auto triItr(facets.begin()); triItr != facets.end(); ) {
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "MeshFeature.h"
|
||||
#include "Core/MeshIO.h"
|
||||
#include "Core/MeshKernel.h"
|
||||
#include "Core/IO/Writer3MF.h"
|
||||
|
||||
namespace Mesh
|
||||
{
|
||||
@@ -91,6 +92,50 @@ protected:
|
||||
std::string fName;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief The Extension3MF class
|
||||
* Abstract base class for 3MF extensions
|
||||
*/
|
||||
class MeshExport Extension3MF
|
||||
{
|
||||
public:
|
||||
using Resource = MeshCore::Resource3MF;
|
||||
Extension3MF() = default;
|
||||
virtual ~Extension3MF() = default;
|
||||
|
||||
virtual Resource addMesh(const MeshObject & mesh) = 0;
|
||||
};
|
||||
|
||||
using Extension3MFPtr = std::shared_ptr<Extension3MF>;
|
||||
|
||||
/*!
|
||||
* \brief The AbstractExtensionProducer class
|
||||
* Abstract base class to create an instance of an Extension3MF.
|
||||
*/
|
||||
class MeshExport AbstractExtensionProducer
|
||||
{
|
||||
public:
|
||||
AbstractExtensionProducer() = default;
|
||||
virtual ~AbstractExtensionProducer() = default;
|
||||
virtual Extension3MFPtr create() const = 0;
|
||||
};
|
||||
|
||||
using AbstractExtensionProducerPtr = std::shared_ptr<AbstractExtensionProducer>;
|
||||
|
||||
/*!
|
||||
* \brief The Extension3MFFactory class
|
||||
* Factor class to manage the producers of Extension3MF
|
||||
*/
|
||||
class MeshExport Extension3MFFactory
|
||||
{
|
||||
public:
|
||||
static void addProducer(AbstractExtensionProducer* ext);
|
||||
static std::vector<Extension3MFPtr> create();
|
||||
|
||||
private:
|
||||
static std::vector<AbstractExtensionProducerPtr> producer;
|
||||
};
|
||||
|
||||
/// Used for exporting to 3D Manufacturing Format (3MF)
|
||||
/*!
|
||||
* The constructor and destructor write the beginning and end of the 3MF,
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <Gui/Language/Translator.h>
|
||||
|
||||
#include <Mod/Mesh/App/MeshProperties.h>
|
||||
#include <Mod/Mesh/App/Exporter.h>
|
||||
|
||||
#include "images.h"
|
||||
#include "DlgEvaluateMeshImp.h"
|
||||
@@ -52,6 +53,7 @@
|
||||
#include "SoFCMeshObject.h"
|
||||
#include "SoFCIndexedFaceSet.h"
|
||||
#include "SoPolygon.h"
|
||||
#include "ThumbnailExtension.h"
|
||||
#include "ViewProvider.h"
|
||||
#include "ViewProviderMeshFaceSet.h"
|
||||
#include "ViewProviderCurvature.h"
|
||||
@@ -163,6 +165,8 @@ PyMOD_INIT_FUNC(MeshGui)
|
||||
(void)new Gui::PrefPageProducer<MeshGui::DlgSettingsMeshView> ("Display");
|
||||
(void)new Gui::PrefPageProducer<MeshGui::DlgSettingsImportExport> ( QT_TRANSLATE_NOOP("QObject", "Import-Export") );
|
||||
|
||||
Mesh::Extension3MFFactory::addProducer(new MeshGui::ThumbnailExtensionProducer);
|
||||
|
||||
MeshGui::SoFCMeshObjectElement ::initClass();
|
||||
MeshGui::SoSFMeshObject ::initClass();
|
||||
MeshGui::SoFCMeshObjectNode ::initClass();
|
||||
|
||||
@@ -144,6 +144,8 @@ SET(MeshGui_SRCS
|
||||
MeshSelection.h
|
||||
PropertyEditorMesh.cpp
|
||||
PropertyEditorMesh.h
|
||||
ThumbnailExtension.cpp
|
||||
ThumbnailExtension.h
|
||||
Workbench.cpp
|
||||
Workbench.h
|
||||
)
|
||||
|
||||
99
src/Mod/Mesh/Gui/ThumbnailExtension.cpp
Normal file
99
src/Mod/Mesh/Gui/ThumbnailExtension.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
/***************************************************************************
|
||||
* 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"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <Inventor/SbRotation.h>
|
||||
#include <Inventor/SbViewportRegion.h>
|
||||
#include <Inventor/nodes/SoCoordinate3.h>
|
||||
#include <Inventor/nodes/SoIndexedFaceSet.h>
|
||||
#include <Inventor/nodes/SoDirectionalLight.h>
|
||||
#include <Inventor/nodes/SoOrthographicCamera.h>
|
||||
#include <Inventor/nodes/SoSeparator.h>
|
||||
#include <QBuffer>
|
||||
#include <QByteArray>
|
||||
#endif
|
||||
|
||||
#include "ThumbnailExtension.h"
|
||||
#include "ViewProvider.h"
|
||||
#include <Gui/SoFCOffscreenRenderer.h>
|
||||
|
||||
using namespace MeshGui;
|
||||
|
||||
Mesh::Extension3MF::Resource ThumbnailExtension3MF::addMesh(const Mesh::MeshObject &mesh)
|
||||
{
|
||||
SoCoordinate3* coord = new SoCoordinate3();
|
||||
SoIndexedFaceSet* faces = new SoIndexedFaceSet();
|
||||
|
||||
SoOrthographicCamera* cam = new SoOrthographicCamera();
|
||||
SoSeparator* root = new SoSeparator();
|
||||
root->ref();
|
||||
root->addChild(cam);
|
||||
root->addChild(new SoDirectionalLight);
|
||||
root->addChild(coord);
|
||||
root->addChild(faces);
|
||||
|
||||
ViewProviderMeshBuilder().createMesh(mesh.getKernel(), coord, faces);
|
||||
|
||||
SbRotation rot(-0.353553, -0.146447, -0.353553, -0.853553);
|
||||
cam->orientation.setValue(rot);
|
||||
SbViewportRegion vpr(256, 256);
|
||||
cam->viewAll(root, vpr);
|
||||
|
||||
Gui::SoQtOffscreenRenderer renderer(vpr);
|
||||
renderer.setBackgroundColor(SbColor4f(1.0f, 1.0f, 1.0f, 0.0f));
|
||||
QImage img;
|
||||
renderer.render(root);
|
||||
renderer.writeToImage(img);
|
||||
root->unref();
|
||||
|
||||
QByteArray data;
|
||||
QBuffer buffer(&data);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
img.save(&buffer, "PNG");
|
||||
buffer.close();
|
||||
|
||||
Mesh::Extension3MF::Resource res;
|
||||
res.extension = "png";
|
||||
res.contentType = "image/png";
|
||||
res.relationshipType = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
|
||||
res.fileContent = std::string(data.data(), data.size());
|
||||
setContentName(res);
|
||||
|
||||
index++;
|
||||
return res;
|
||||
}
|
||||
|
||||
void ThumbnailExtension3MF::setContentName(Mesh::Extension3MF::Resource& res)
|
||||
{
|
||||
if (index == 0) {
|
||||
res.relationshipTarget = "/Metadata/thumbnail.png";
|
||||
res.fileNameInZip = "Metadata/thumbnail.png";
|
||||
}
|
||||
else {
|
||||
std::string suf = std::to_string(index);
|
||||
res.relationshipTarget = "/Metadata/thumbnail" + suf + ".png";
|
||||
res.fileNameInZip = "Metadata/thumbnail" + suf + ".png";
|
||||
}
|
||||
}
|
||||
52
src/Mod/Mesh/Gui/ThumbnailExtension.h
Normal file
52
src/Mod/Mesh/Gui/ThumbnailExtension.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/***************************************************************************
|
||||
* 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 MESHGUI_THUMBNAIL_EXTENSION_H
|
||||
#define MESHGUI_THUMBNAIL_EXTENSION_H
|
||||
|
||||
#include <Mod/Mesh/MeshGlobal.h>
|
||||
#include <Mod/Mesh/App/Exporter.h>
|
||||
|
||||
namespace MeshGui {
|
||||
|
||||
class ThumbnailExtension3MF : public Mesh::Extension3MF {
|
||||
public:
|
||||
Mesh::Extension3MF::Resource addMesh(const Mesh::MeshObject & mesh) override;
|
||||
|
||||
private:
|
||||
void setContentName(Mesh::Extension3MF::Resource&);
|
||||
|
||||
private:
|
||||
int index = 0;
|
||||
};
|
||||
|
||||
class ThumbnailExtensionProducer : public Mesh::AbstractExtensionProducer {
|
||||
public:
|
||||
Mesh::Extension3MFPtr create() const override {
|
||||
return std::make_shared<ThumbnailExtension3MF>();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace MeshGui
|
||||
|
||||
|
||||
#endif // MESHGUI_THUMBNAIL_EXTENSION_H
|
||||
@@ -142,10 +142,15 @@ void ViewProviderMeshBuilder::createMesh(const App::Property* prop, SoCoordinate
|
||||
{
|
||||
const Mesh::PropertyMeshKernel* mesh = static_cast<const Mesh::PropertyMeshKernel*>(prop);
|
||||
const MeshCore::MeshKernel& rcMesh = mesh->getValue().getKernel();
|
||||
createMesh(rcMesh, coords, faces);
|
||||
}
|
||||
|
||||
void ViewProviderMeshBuilder::createMesh(const MeshCore::MeshKernel& kernal, SoCoordinate3* coords, SoIndexedFaceSet* faces) const
|
||||
{
|
||||
|
||||
// set the point coordinates
|
||||
const MeshCore::MeshPointArray& cP = rcMesh.GetPoints();
|
||||
coords->point.setNum(rcMesh.CountPoints());
|
||||
const MeshCore::MeshPointArray& cP = kernal.GetPoints();
|
||||
coords->point.setNum(kernal.CountPoints());
|
||||
SbVec3f* verts = coords->point.startEditing();
|
||||
int i=0;
|
||||
for (MeshCore::MeshPointArray::_TConstIterator it = cP.begin(); it != cP.end(); ++it, i++) {
|
||||
@@ -155,8 +160,8 @@ void ViewProviderMeshBuilder::createMesh(const App::Property* prop, SoCoordinate
|
||||
|
||||
// set the face indices
|
||||
int j=0;
|
||||
const MeshCore::MeshFacetArray& cF = rcMesh.GetFacets();
|
||||
faces->coordIndex.setNum(4*rcMesh.CountFacets());
|
||||
const MeshCore::MeshFacetArray& cF = kernal.GetFacets();
|
||||
faces->coordIndex.setNum(4*kernal.CountFacets());
|
||||
int32_t* indices = faces->coordIndex.startEditing();
|
||||
for (MeshCore::MeshFacetArray::_TConstIterator it = cF.begin(); it != cF.end(); ++it, j++) {
|
||||
for (int i=0; i<3; i++) {
|
||||
|
||||
@@ -82,6 +82,7 @@ public:
|
||||
~ViewProviderMeshBuilder() override{}
|
||||
void buildNodes(const App::Property*, std::vector<SoNode*>&) const override;
|
||||
void createMesh(const App::Property*, SoCoordinate3*, SoIndexedFaceSet*) const;
|
||||
void createMesh(const MeshCore::MeshKernel&, SoCoordinate3*, SoIndexedFaceSet*) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user