Mesh: [skip ci] support of WebGL/X3D export

This commit is contained in:
wmayer
2020-08-28 18:06:55 +02:00
parent dbcf003f34
commit c06a4d462b
4 changed files with 106 additions and 4 deletions

View File

@@ -1772,6 +1772,7 @@ std::vector<std::string> MeshOutput::supportedMeshFormats()
fmt.emplace_back("off");
fmt.emplace_back("smf");
fmt.emplace_back("x3d");
fmt.emplace_back("html");
fmt.emplace_back("wrl");
fmt.emplace_back("wrz");
fmt.emplace_back("amf");
@@ -1812,6 +1813,9 @@ MeshIO::Format MeshOutput::GetFormat(const char* FileName)
else if (file.hasExtension("x3d")) {
return MeshIO::X3D;
}
else if (file.hasExtension("html")) {
return MeshIO::HTML;
}
else if (file.hasExtension("py")) {
return MeshIO::PY;
}
@@ -1924,6 +1928,11 @@ bool MeshOutput::SaveAny(const char* FileName, MeshIO::Format format) const
if (!SaveX3D(str))
throw Base::FileException("Export of X3D failed",FileName);
}
else if (fileformat == MeshIO::HTML) {
// write file
if (!SaveHTML(str))
throw Base::FileException("Export of HTML failed",FileName);
}
else if (fileformat == MeshIO::PY) {
// write file
if (!SavePython(str))
@@ -1987,6 +1996,8 @@ bool MeshOutput::SaveFormat(std::ostream &str, MeshIO::Format fmt) const
return SaveInventor(str);
case MeshIO::X3D:
return SaveX3D(str);
case MeshIO::HTML:
return SaveHTML(str);
case MeshIO::VRML:
return SaveVRML(str);
case MeshIO::WRZ:
@@ -3003,22 +3014,36 @@ bool MeshOutput::SaveInventor (std::ostream &rstrOut) const
/** Writes an X3D file. */
bool MeshOutput::SaveX3D (std::ostream &out) const
{
if ((!out) || (out.bad() == true) || (_rclMesh.CountFacets() == 0))
return false;
// XML header info
out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
return SaveX3DContent(out);
}
/** Writes an X3D file. */
bool MeshOutput::SaveX3DContent (std::ostream &out) const
{
if ((!out) || (out.bad() == true) || (_rclMesh.CountFacets() == 0))
return false;
const MeshPointArray& pts = _rclMesh.GetPoints();
const MeshFacetArray& fts = _rclMesh.GetFacets();
Base::BoundBox3f bbox = _rclMesh.GetBoundBox();
if (apply_transform)
bbox = bbox.Transformed(_transform);
Base::SequencerLauncher seq("Saving...", _rclMesh.CountFacets() + 1);
out.precision(6);
out.setf(std::ios::fixed | std::ios::showpoint);
// Header info
out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
out << "<X3D profile=\"Immersive\" version=\"3.2\" xmlns:xsd="
<< "\"http://www.w3.org/2001/XMLSchema-instance\" xsd:noNamespaceSchemaLocation="
<< "\"http://www.web3d.org/specifications/x3d-3.2.xsd\">\n";
<< "\"http://www.web3d.org/specifications/x3d-3.2.xsd\" width=\"1280px\" height=\"1024px\">\n";
out << " <head>\n"
<< " <meta name=\"generator\" content=\"FreeCAD\"/>\n"
<< " <meta name=\"author\" content=\"\"/> \n"
@@ -3026,7 +3051,34 @@ bool MeshOutput::SaveX3D (std::ostream &out) const
<< " </head>\n";
// Beginning
out << " <Scene>\n";
out << " <Scene DEF='scene'>\n";
auto viewpoint = [&out](const char* text, const Base::Vector3f& cnt,
const Base::Vector3f& pos, const Base::Vector3f& axis, float angle) {
out << " <Viewpoint id=\"" << text
<< "\" centerOfRotation=\"" << cnt.x << " " << cnt.y << " " << cnt.z
<< "\" position=\"" << pos.x << " " << pos.y << " " << pos.z
<< "\" orientation=\"" << axis.x << " " << axis.y << " " << axis.z << " " << angle
<< "\" description=\"camera\" fieldOfView=\"0.9\">"
<< "</Viewpoint>\n";
};
Base::Vector3f cnt = bbox.GetCenter();
float minx = bbox.MinX;
float maxx = bbox.MaxX;
float miny = bbox.MinY;
float maxy = bbox.MaxY;
float minz = bbox.MinZ;
float maxz = bbox.MaxZ;
float len = bbox.CalcDiagonalLength();
viewpoint("Front", cnt, Base::Vector3f(cnt.x, miny-len, cnt.z), Base::Vector3f(1.0f, 0.0f, 0.0f), 1.5707964f);
viewpoint("Back", cnt, Base::Vector3f(cnt.x, maxy+len, cnt.z), Base::Vector3f(0.0f, 0.707106f, 0.707106f), 3.141592f);
viewpoint("Right", cnt, Base::Vector3f(maxx+len, cnt.y, cnt.z), Base::Vector3f(0.577350f, 0.577350f, 0.577350f), 2.094395f);
viewpoint("Left", cnt, Base::Vector3f(minx-len, cnt.y, cnt.z), Base::Vector3f(-0.577350f, 0.577350f, 0.577350f), 4.188790f);
viewpoint("Top", cnt, Base::Vector3f(cnt.x, cnt.y, maxz+len), Base::Vector3f(0.0f, 0.0f, 1.0f), 0.0f);
viewpoint("Bottom", cnt, Base::Vector3f(cnt.x, cnt.y, minz-len), Base::Vector3f(1.0f, 0.0f, 0.0f), 3.141592f);
if (apply_transform) {
Base::Placement p(_transform);
const Base::Vector3d& v = p.getPosition();
@@ -3067,12 +3119,54 @@ bool MeshOutput::SaveX3D (std::ostream &out) const
out << " </IndexedFaceSet>\n"
<< " </Shape>\n"
<< " </Transform>\n"
<< " <Background groundColor=\"0.7 0.7 0.7\" skyColor=\"0.7 0.7 0.7\" />\n"
<< " <NavigationInfo/>\n"
<< " </Scene>\n"
<< "</X3D>\n";
return true;
}
/** Writes an HTML file. */
bool MeshOutput::SaveHTML (std::ostream &out) const
{
if ((!out) || (out.bad() == true) || (_rclMesh.CountFacets() == 0))
return false;
out << "<html>\n"
<< " <head>\n"
<< " <script type='text/javascript' src='http://www.x3dom.org/download/x3dom.js'> </script>\n"
<< " <link rel='stylesheet' type='text/css' href='http://www.x3dom.org/download/x3dom.css'></link>\n"
<< " </head>\n";
#if 0 // https://stackoverflow.com/questions/32305678/x3dom-how-to-make-zoom-buttons
function zoom (delta) {
var x3d = document.getElementById("right");
var vpt = x3d.getElementsByTagName("Viewpoint")[0];
vpt.fieldOfView = parseFloat(vpt.fieldOfView) + delta;
}
<button onclick="zoom(0.15);">Zoom out</button>
#endif
SaveX3DContent(out);
auto onclick = [&out](const char* text) {
out << " <button onclick=\"document.getElementById('" << text << "').setAttribute('set_bind','true');\">" << text << "</button>\n";
};
onclick("Front");
onclick("Back");
onclick("Right");
onclick("Left");
onclick("Top");
onclick("Bottom");
out << "</html>\n";
return true;
}
/** Writes a Nastran file. */
bool MeshOutput::SaveNastran (std::ostream &rstrOut) const
{

View File

@@ -50,6 +50,7 @@ namespace MeshIO {
MGL,
IV,
X3D,
HTML,
VRML,
WRZ,
NAS,
@@ -201,6 +202,8 @@ public:
bool SaveInventor (std::ostream &rstrOut) const;
/** Writes an X3D file. */
bool SaveX3D (std::ostream &rstrOut) const;
/** Writes an HTML file. */
bool SaveHTML (std::ostream &rstrOut) const;
/** Writes a VRML file. */
bool SaveVRML (std::ostream &rstrOut) const;
/** Writes a Nastran file. */
@@ -212,6 +215,10 @@ public:
static std::vector<std::string> supportedMeshFormats();
protected:
/** Writes an X3D file. */
bool SaveX3DContent (std::ostream &rstrOut) const;
protected:
const MeshKernel &_rclMesh; /**< reference to mesh data structure */
const Material* _material;

View File

@@ -177,7 +177,6 @@ PyObject* MeshPy::read(PyObject *args, PyObject *kwds)
ext["PLY" ] = MeshCore::MeshIO::PLY;
ext["APLY"] = MeshCore::MeshIO::APLY;
ext["PY" ] = MeshCore::MeshIO::PY;
ext["ASY" ] = MeshCore::MeshIO::ASY;
PyObject* input;
char* Ext;
@@ -221,6 +220,7 @@ PyObject* MeshPy::write(PyObject *args, PyObject *kwds)
ext["MGL" ] = MeshCore::MeshIO::MGL;
ext["IV" ] = MeshCore::MeshIO::IV;
ext["X3D" ] = MeshCore::MeshIO::X3D;
ext["HTML"] = MeshCore::MeshIO::HTML;
ext["VRML"] = MeshCore::MeshIO::VRML;
ext["WRL" ] = MeshCore::MeshIO::VRML;
ext["WRZ" ] = MeshCore::MeshIO::WRZ;

View File

@@ -516,6 +516,7 @@ void CmdMeshExport::activated(int)
ext << qMakePair<QString, QByteArray>(QString::fromLatin1("%1 (*.off)").arg(QObject::tr("Object File Format")), "OFF");
ext << qMakePair<QString, QByteArray>(QString::fromLatin1("%1 (*.iv)").arg(QObject::tr("Inventor V2.1 ascii")), "IV");
ext << qMakePair<QString, QByteArray>(QString::fromLatin1("%1 (*.x3d)").arg(QObject::tr("X3D Extensible 3D")), "X3D");
ext << qMakePair<QString, QByteArray>(QString::fromLatin1("%1 (*.html)").arg(QObject::tr("WebGL/X3D")), "HTML");
ext << qMakePair<QString, QByteArray>(QString::fromLatin1("%1 (*.ply)").arg(QObject::tr("Stanford Polygon")), "PLY");
ext << qMakePair<QString, QByteArray>(QString::fromLatin1("%1 (*.wrl *.vrml)").arg(QObject::tr("VRML V2.0")), "VRML");
ext << qMakePair<QString, QByteArray>(QString::fromLatin1("%1 (*.wrz)").arg(QObject::tr("Compressed VRML 2.0")), "WRZ");