/*
* Copyright (C) 2010 Sebastian Held (sebastian.held@gmx.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "CSPrimBox.h"
#include "CSPrimPolygon.h"
#include "QVTKStructure.h"
#include "QCSXCAD.h"
#include "export_x3d.h"
export_X3D::export_X3D( QCSXCAD *CSX ) : m_CSX(CSX)
{
}
void export_X3D::save( QString filename )
{
QDomImplementation impl;
QDomDocument doc( impl.createDocumentType ( "X3D", "ISO//Web3D//DTD X3D 3.2//EN", "http://www.web3d.org/specifications/x3d-3.2.dtd" ) );
doc.appendChild( doc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" )); // FIXME this is not a processing instruction!
QDomElement X3D = doc.createElement( "X3D" );
X3D.setAttribute( "version", "3.2" );
X3D.setAttribute( "profile", "Immersive" );
doc.appendChild( X3D );
QDomElement head = doc.createElement( "head" );
X3D.appendChild( head );
QDomElement meta = doc.createElement( "meta" );
meta.setAttribute( "name", "description" );
meta.setAttribute( "content", "X3D model exported by QCSXCAD" );
head.appendChild( meta );
QDomElement Scene = doc.createElement( "Scene" );
X3D.appendChild( Scene );
QDomElement NavigationInfo = doc.createElement( "NavigationInfo" );
NavigationInfo.setAttribute( "headlight", "true" );
// NavigationInfo.setAttribute( "avatarSize", "0.25 1.6 0.75" );
NavigationInfo.setAttribute( "type", "EXAMINE" );
Scene.appendChild( NavigationInfo );
std::vector properties = m_CSX->GetPropertyByType( CSProperties::MATERIAL );
export_properties( Scene, properties );
properties = m_CSX->GetPropertyByType( CSProperties::METAL );
QDomElement Material = doc.createElement( "Material" );
Material.setAttribute( "diffuseColor", "0.0 1.0 0.0" );
export_properties( Scene, properties, Material );
// create camera
vtkRendererCollection* collection = ((QVTKWidget*)(m_CSX->StructureVTK->GetVTKWidget()))->GetRenderWindow()->GetRenderers();
vtkRenderer *r = collection->GetFirstRenderer();
if (!r)
return;
vtkCamera *c = r->GetActiveCamera();
if (!c)
return;
QDomElement Viewpoint = doc.createElement( "Viewpoint" );
double *pos = c->GetPosition();
Viewpoint.setAttribute( "position", QString::number(pos[0]) + " " + QString::number(pos[1]) + " " + QString::number(pos[2]) );
// double *focalpos = c->GetFocalPoint();
// Viewpoint.setAttribute( "centerOfRotation", QString::number(focalpos[0]) + " " + QString::number(focalpos[1]) + " " + QString::number(focalpos[2]) );
double angle = c->GetViewAngle();
Viewpoint.setAttribute( "fieldOfView", QString::number(angle/180.0*M_PI) );
double *WXYZ = c->GetOrientationWXYZ();
Viewpoint.setAttribute( "orientation", QString::number(WXYZ[1]) + " " + QString::number(WXYZ[2]) + " " + QString::number(WXYZ[3]) + " " + QString::number((360.0-WXYZ[0])/180.0*M_PI) ); // WXYZ[0] is wrong VTK-BUG!?
Scene.appendChild( Viewpoint );
// cout << doc.toString(4).toStdString() << endl;
QFile file( filename );
if (!file.open( QFile::WriteOnly )) {
QMessageBox::warning( m_CSX, QObject::tr("save failed"), QObject::tr("Cannot save to the file %1").arg(filename), QMessageBox::Ok );
return;
}
QTextStream stream(&file);
stream.setCodec( "UTF-8" );
doc.save( stream, 4, QDomNode::EncodingFromTextStream );
}
void export_X3D::export_properties( QDomElement Scene, std::vector properties, QDomElement Material )
{
foreach( CSProperties* prop, properties )
{
int size = prop->GetQtyPrimitives();
for( int i=0; iGetPrimitive(i);
if (prim->GetType() == CSPrimitives::BOX)
{
CSPrimBox *box = prim->ToBox();
double start[] = {box->GetCoord(0),box->GetCoord(2),box->GetCoord(4)};
double stop[] = {box->GetCoord(1),box->GetCoord(3),box->GetCoord(5)};
export_box( Scene, start, stop, Material.cloneNode().toElement() );
}
else if (prim->GetType() == CSPrimitives::POLYGON)
{
CSPrimPolygon *polygon = prim->ToPolygon();
size_t count = -1;
double *array = 0;
array = polygon->GetAllCoords( count, array );
int normDir = polygon->GetNormDir();
double elevation = polygon->GetElevation();
export_polygon( Scene, count, array, elevation, normDir, Material.cloneNode().toElement() );
}
}
}
}
void export_X3D::export_box( QDomElement &elem, double start[3], double stop[3], QDomElement Material )
{
double center[3], size[3];
for (int i=0; i<3; i++)
{
center[i] = (stop[i]+start[i])/2.0;// * GetGrid()->GetDeltaUnit();
size[i] = fabs(stop[i]-start[i]);// * GetGrid()->GetDeltaUnit();
}
QDomDocument doc = elem.ownerDocument();
QDomElement Transform = doc.createElement( "Transform" );
Transform.setAttribute( "translation", QString::number(center[0]) + " " + QString::number(center[1]) + " " + QString::number(center[2]) );
QDomElement Shape = doc.createElement( "Shape" );
Transform.appendChild( Shape );
QDomElement Box = doc.createElement( "Box" );
Box.setAttribute( "size", QString::number(size[0]) + " " + QString::number(size[1]) + " " + QString::number(size[2]) );
Shape.appendChild( Box );
QDomElement Appearance = doc.createElement( "Appearance" );
Shape.appendChild( Appearance );
if (Material.isNull())
{
Material = doc.createElement( "Material" );
Material.setAttribute( "diffuseColor", "1.0 0.0 0.0" );
}
Appearance.appendChild( Material );
elem.appendChild( Transform );
}
void export_X3D::export_polygon( QDomElement &elem, size_t count, double *array, double elevation, int normDir, QDomElement Material )
{
if (count < 2)
return;
// VRML: cross section in xz-plane
QString crossSection;
crossSection = QString::number( array[0] ) + " " + QString::number( array[1] );
for (size_t i=2; i