1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
|
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <QMessageBox>
#include <QtXml>
#include <QVTKWidget.h>
#include <vtkRendererCollection.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkCamera.h>
#include <vector>
#include <ContinuousStructure.h>
#include "CSPrimBox.h"
#include "CSPrimCylinder.h"
#include "CSPrimPolygon.h"
#include "CSPrimCurve.h"
#include "CSPrimWire.h"
#include "QVTKStructure.h"
#include "QCSXCAD.h"
#include "export_pov.h"
export_pov::export_pov( QCSXCAD *CSX ) : m_CSX(CSX)
{
m_epsilon = 1; // FIXME this should be small compared to any other linear dimension of any object in the scene
}
void export_pov::save( QString filename )
{
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" );
stream << "// povray-file exported by QCSXCAD" << endl;
stream << "// render with:" << endl;
stream << "// povray -W640 -H480 +A " << QFileInfo(filename).fileName() << endl;
stream << endl;
stream << "#declare TRANSPARENT = off; // if on, also use the \"+ua\" command line flag" << endl;
stream << endl;
stream << "#include \"colors.inc\"" << endl;
stream << "#include \"metals.inc\"" << endl;
stream << "#include \"textures.inc\"" << endl;
stream << "#include \"transforms.inc\"" << endl;
stream << "background { color rgb<1.000000,1.000000,1.000000> #if(TRANSPARENT) transmit 1.0 #end }" << endl;
// export material
std::vector<CSProperties*> properties = m_CSX->GetPropertyByType( CSProperties::MATERIAL );
export_properties( stream, properties, "pigment { color rgbt <0.000, 0.533, 0.800,0.0> } finish { diffuse 0.6 }" );
// export metal
properties = m_CSX->GetPropertyByType( CSProperties::METAL );
export_properties( stream, properties, "texture { Copper_Metal }" );
// create camera
stream << get_camera() << endl;
// create light
stream << get_light() << endl;
stream.flush();
file.close();
}
void export_pov::export_properties( QTextStream &stream, std::vector<CSProperties*> properties, QString default_obj_modifier )
{
foreach( CSProperties* prop, properties )
{
int size = prop->GetQtyPrimitives();
for( int i=0; i<size; i++ )
{
CSPrimitives *prim = prop->GetPrimitive(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( stream, start, stop, default_obj_modifier );
}
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( stream, count, array, elevation, normDir, default_obj_modifier );
}
else if (prim->GetType() == CSPrimitives::CYLINDER)
{
CSPrimCylinder *primitive = prim->ToCylinder();
double start[] = {primitive->GetCoord(0),primitive->GetCoord(2),primitive->GetCoord(4)};
double stop[] = {primitive->GetCoord(1),primitive->GetCoord(3),primitive->GetCoord(5)};
double radius = primitive->GetRadius();
export_cylinder( stream, start, stop, radius, default_obj_modifier );
}
else if (prim->GetType() == CSPrimitives::WIRE)
{
CSPrimWire *primitive = prim->ToWire();
double radius = primitive->GetWireRadius();
size_t count = primitive->GetNumberOfPoints();
double *array = new double[count*3];
for (unsigned int i=0; i<count; i++)
primitive->GetPoint(i,array+i*3, CARTESIAN);
export_wire( stream, count, array, radius, default_obj_modifier );
delete[] array;
}
else if (prim->GetType() == CSPrimitives::CURVE)
{
CSPrimCurve *primitive = prim->ToCurve();
double radius = m_epsilon;
size_t count = primitive->GetNumberOfPoints();
double *array = new double[count*3];
for (unsigned int i=0; i<count; i++)
primitive->GetPoint(i,array+i*3, CARTESIAN);
export_wire( stream, count, array, radius, default_obj_modifier );
delete[] array;
}
}
}
}
void export_pov::export_box( QTextStream &stream, double start[3], double stop[3], QString object_modifier )
{
for (int i=0; i<3; i++)
if (start[i] == stop[i]) {
// 2D box
// povray supports 2D polygons, but has no priority concept, therefore we use the box primitive
start[i] -= m_epsilon;
stop[i] += m_epsilon;
}
QString box = "box { %1, %2 %3 }";
box = box.arg(pov_vect(start),pov_vect(stop),object_modifier);
stream << box << endl;
}
void export_pov::export_polygon( QTextStream &stream, size_t count, double *array, double elevation, int normDir, QString object_modifier )
{
UNUSED(normDir);
Q_ASSERT((count%2)==0);
count = count / 2; // now count is the number of 2D-vectors
if (count < 2)
return;
elevation = -elevation;
//NormDir = [CSX_polygon.NormDir.ATTRIBUTE.X CSX_polygon.NormDir.ATTRIBUTE.Y CSX_polygon.NormDir.ATTRIBUTE.Z];
QString str = "prism { linear_spline linear_sweep %1, %2, %3";
str = str.arg(elevation - m_epsilon).arg(elevation + m_epsilon).arg(count+1);
for (unsigned int a=0; a<count; a++)
{
// iterate over all vertices
str += ", " + pov_vect2( array + a*2 );
}
str += ", " + pov_vect2( array ); // close the prism
str += " " + object_modifier + " rotate<-90,0,0> }";
stream << str << endl;
}
void export_pov::export_cylinder( QTextStream &stream, double start[3], double stop[3], double radius, QString object_modifier )
{
QString str = "cylinder { %1, %2, %3 %4 }";
str = str.arg(pov_vect(start)).arg(pov_vect(stop)).arg(radius).arg(object_modifier);
stream << str << endl;
}
void export_pov::export_wire( QTextStream &stream, size_t count, double *array, double radius, QString object_modifier )
{
QString str = "sphere_sweep { linear_spline, " + QString::number(count);
for (unsigned int a=0; a<count; a++)
{
// iterate over all vertices
str += ", " + pov_vect(array+a*3) + ", " + QString::number(radius);
}
str += " " + object_modifier + " }";
stream << str << endl;
}
QString export_pov::get_camera()
{
vtkRendererCollection* collection = ((QVTKWidget*)(m_CSX->StructureVTK->GetVTKWidget()))->GetRenderWindow()->GetRenderers();
vtkRenderer *r = collection->GetFirstRenderer();
if (!r)
return QString();
vtkCamera *c = r->GetActiveCamera();
if (!c)
return QString();
double *pos = c->GetPosition();
// cout << "Camera position: " << pos[0] << ", " << pos[1] << ", " << pos[2] << endl;
double *focalpos = c->GetFocalPoint();
// cout << "Camera focal point: " << focalpos[0] << ", " << focalpos[1] << ", " << focalpos[2] << endl;
// double distance = c->GetDistance();
// cout << "Camera distance (position to focal point): " << distance << endl;
// double roll = c->GetRoll();
// cout << "Camera roll angle (about direction of projection): " << roll << "°" << endl;
double angle = c->GetViewAngle();
// cout << "Camera view angle: " << angle << "°" << endl;
double *up = c->GetViewUp();
// cout << "Camera up vector: " << up[0] << ", " << up[1] << ", " << up[2] << endl;
QString camera_str;
camera_str = "camera { perspective location %1 look_at %2 sky %3 right -1.33*x angle %4 }";
camera_str = camera_str.arg(pov_vect(pos),pov_vect(focalpos),pov_vect(up)).arg(angle);
return camera_str;
}
QString export_pov::get_light()
{
vtkRendererCollection* collection = ((QVTKWidget*)(m_CSX->StructureVTK->GetVTKWidget()))->GetRenderWindow()->GetRenderers();
vtkRenderer *r = collection->GetFirstRenderer();
if (!r)
return QString();
vtkCamera *c = r->GetActiveCamera();
if (!c)
return QString();
double *pos = c->GetPosition();
// double *focalpos = c->GetFocalPoint();
// double distance = c->GetDistance();
// double roll = c->GetRoll();
// double angle = c->GetViewAngle();
// double *up = c->GetViewUp();
QString light_str;
light_str = "light_source { %1, rgb <1,1,1> }";
light_str = light_str.arg(pov_vect(pos));
return light_str;
}
QString export_pov::pov_vect( double *v )
{
QString v_str = "<%1,%2,%3>";
v_str = v_str.arg(v[0]).arg(v[1]).arg(v[2]);
return v_str;
}
QString export_pov::pov_vect2( double *v )
{
QString v_str = "<%1,%2>";
v_str = v_str.arg(v[0]).arg(v[1]);
return v_str;
}
|