Gui: use utility tovrmlx3d to convert a VRML 2.0 file into X3D format

This commit is contained in:
wmayer
2020-09-01 16:11:09 +02:00
parent 8329c8434e
commit 64d7c1b052
2 changed files with 137 additions and 1 deletions

View File

@@ -28,6 +28,10 @@
# include <Inventor/VRMLnodes/SoVRMLParent.h>
# include <Inventor/SbString.h>
# include <Inventor/nodes/SoGroup.h>
# include <QDir>
# include <QProcess>
# include <QTemporaryFile>
# include <sstream>
#endif
#include <Base/FileInfo.h>
@@ -359,6 +363,116 @@ bool Gui::SoFCDB::writeToVRML(SoNode* node, const char* filename, bool binary)
return false;
}
bool Gui::SoFCDB::writeToX3D(SoNode* node, const char* filename, bool binary)
{
std::string buffer;
writeToX3D(node, buffer);
Base::FileInfo fi(filename);
if (binary) {
Base::ofstream str(fi, std::ios::out | std::ios::binary);
zipios::GZIPOutputStream gzip(str);
if (gzip) {
gzip << buffer;
gzip.close();
return true;
}
}
else {
Base::ofstream str(fi, std::ios::out);
if (str) {
str << buffer;
str.close();
return true;
}
}
return false;
}
bool Gui::SoFCDB::writeToX3D(SoNode* node, std::string& buffer)
{
writeToVRML(node, buffer);
if (buffer.empty())
return false;
QString filename = QDir::tempPath();
filename += QLatin1String("/sceneXXXXXX.wrl");
QTemporaryFile wrlFile(filename);
if (wrlFile.open()) {
filename = wrlFile.fileName();
wrlFile.write(buffer.c_str(), buffer.size());
wrlFile.close();
QString exe(QLatin1String("tovrmlx3d"));
QStringList args;
args << filename << QLatin1String("--encoding") << QLatin1String("xml");
QProcess proc;
proc.setEnvironment(QProcess::systemEnvironment());
proc.start(exe, args);
if (proc.waitForStarted() && proc.waitForFinished()) {
QByteArray x3d = proc.readAll();
if (x3d.isEmpty())
return false;
x3d.replace('\t', " ");
// compute a sensible view point
SoGetBoundingBoxAction bboxAction(SbViewportRegion(1280, 1024));
bboxAction.apply(node);
SbBox3f bbox = bboxAction.getBoundingBox();
SbSphere bs;
bs.circumscribe(bbox);
const SbVec3f& cnt = bs.getCenter();
float dist = bs.getRadius();
QString vp = QString::fromLatin1(" <Viewpoint id=\"Top\" centerOfRotation=\"%1 %2 %3\" "
"position=\"%1 %2 %4\" orientation=\"0.000000 0.000000 1.000000 0.000000\" "
"description=\"camera\" fieldOfView=\"0.9\"></Viewpoint>\n")
.arg(cnt[0]).arg(cnt[1]).arg(cnt[2]).arg(cnt[2] + 2.0f * dist);
int index = x3d.indexOf("<Scene>\n");
if (index >= 0) {
x3d.insert(index + 8, vp);
}
buffer = x3d.data();
return true;
}
}
return false;
}
bool Gui::SoFCDB::writeToX3DOM(SoNode* node, std::string& buffer)
{
std::string x3d;
if (!writeToX3D(node, x3d))
return false;
// remove the first two lines from the x3d output as this duplicates
// the xml and doctype header
std::size_t pos = x3d.find('\n');
pos = x3d.find('\n', pos + 1);
x3d = x3d.erase(0, pos + 1);
std::stringstream out;
out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
<< "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
out << "<html xmlns='http://www.w3.org/1999/xhtml'>\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";
out << x3d;
out << "</html>\n";
buffer = out.str();
return true;
}
bool Gui::SoFCDB::writeToFile(SoNode* node, const char* filename, bool binary)
{
bool ret = false;
@@ -372,6 +486,25 @@ bool Gui::SoFCDB::writeToFile(SoNode* node, const char* filename, bool binary)
ret = SoFCDB::writeToVRML(node, filename, binary);
}
else if (fi.hasExtension("x3d") || fi.hasExtension("x3dz")) {
// If 'x3dz' is set then force compression
if (fi.hasExtension("x3dz"))
binary = true;
ret = SoFCDB::writeToX3D(node, filename, binary);
}
else if (fi.hasExtension("xhtml")) {
std::string buffer;
if (SoFCDB::writeToX3DOM(node, buffer)) {
Base::ofstream str(Base::FileInfo(filename), std::ios::out);
if (str) {
str << buffer;
str.close();
ret = true;
}
}
}
else if (fi.hasExtension("iv")) {
// Write Inventor in ASCII
std::string buffer = SoFCDB::writeNodesToString(node);

View File

@@ -45,7 +45,10 @@ public:
static const std::string& writeNodesToString(SoNode * root);
static bool writeToVRML(SoNode* node, const char* filename, bool binary);
static void writeToVRML(SoNode* node, std::string& buffer);
// Write to VRML or Inventor file
static bool writeToX3D(SoNode* node, const char* filename, bool binary);
static bool writeToX3D(SoNode* node, std::string& buffer);
static bool writeToX3DOM(SoNode* node, std::string& buffer);
// Write to Inventor, VRML, X3D or XHTML (based on X3DOM) file
static bool writeToFile(SoNode* node, const char* filename, bool binary);
/*! container for app lifetime storage. See SoFCCSysDragger for details
* on why this is needed.