some fixes to the cmake files. It still is not working
[kdeedu-porting.git] / kalzium / libavogadro-kalzium / src / povpainter.cpp
blobd303f01b2df52cd1c830ff1f2ff56010cab34b25
1 /**********************************************************************
2 POVPainter - drawing spheres, cylinders and text in a POVRay scene
4 Copyright (C) 2007 Marcus D. Hanwell
6 This file is part of the Avogadro molecular editor project.
7 For more information, see <http://avogadro.sourceforge.net/>
9 Avogadro is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 Avogadro is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 02110-1301, USA.
23 **********************************************************************/
25 #include "povpainter.h"
27 #include <QFile>
28 #include <QDebug>
30 namespace Avogadro
32 class POVPainterPrivate
34 public:
35 POVPainterPrivate() : pd (0), initialized (false), sharing(0),
36 color(0), output(0), planeNormalVector(0., 0., 0.) { color.set(0., 0., 0., 0.); }
37 ~POVPainterPrivate()
41 POVPainterDevice *pd;
43 bool initialized;
45 inline bool isValid();
47 /**
48 * Painters can be shared, we must keep track of this.
50 int sharing;
52 Color color;
53 QTextStream *output;
54 Vector3d planeNormalVector;
58 POVPainter::POVPainter() : d (new POVPainterPrivate)
63 POVPainter::~POVPainter()
68 void POVPainter::setColor (const Color *color)
70 d->color = *color;
73 void POVPainter::setColor (float red, float green, float blue, float alpha)
75 d->color = Color(red, green, blue, alpha);
78 void POVPainter::setPlaneNormal (Vector3d planeNormalVector)
80 // Set the plane normal, multiCylinders are drawn relative to this
81 d->planeNormalVector = planeNormalVector;
84 void POVPainter::drawSphere (const Vector3d & center, double radius)
86 // Write out a POVRay sphere for rendering
87 *(d->output) << "sphere {\n"
88 << "\t<" << center.x() << ", " << center.y() << ", " << center.z() << ">, " << radius
89 << "\n\tpigment { rgbf <" << d->color.red() << ", " << d->color.green() << ", "
90 << d->color.blue() << ", " << 1.0 - d->color.alpha() << "> }\n}\n";
93 void POVPainter::drawCylinder (const Vector3d &end1, const Vector3d &end2,
94 double radius)
96 // Write out a POVRay cylinder for rendering
97 *(d->output) << "cylinder {\n"
98 << "\t<" << end1.x() << ", " << end1.y() << ", " << end1.z() << ">, "
99 << "\t<" << end2.x() << ", " << end2.y() << ", " << end2.z() << ">, " << radius
100 << "\n\tpigment { rgbf <" << d->color.red() << ", " << d->color.green() << ", "
101 << d->color.blue() << ", " << 1.0 - d->color.alpha() << "> }\n}\n";
104 void POVPainter::drawMultiCylinder (const Vector3d &end1, const Vector3d &end2,
105 double radius, int order, double)
107 // Just render single bonds with the standard drawCylinder function
108 if (order == 1)
110 drawCylinder(end1, end2, radius);
111 return;
114 // Find the bond axis
115 Vector3d axis = end2 - end1;
116 double axisNorm = axis.norm();
117 if( axisNorm == 0.0 ) return;
118 Vector3d axisNormalized = axis / axisNorm;
120 // Use the plane normal vector for the molecule to draw multicylinders along
121 Vector3d ortho1 = axisNormalized.cross(d->planeNormalVector);
122 double ortho1Norm = ortho1.norm();
123 if( ortho1Norm > 0.001 ) ortho1 /= ortho1Norm;
124 else ortho1 = axisNormalized.ortho();
125 // This number seems to work well for drawing the multiCylinder inside
126 ortho1 *= radius*1.5;
127 Vector3d ortho2 = cross( axisNormalized, ortho1 );
128 // Use an angle offset of zero for double bonds, 90 for triple and 22.5 for higher order
129 double angleOffset = 0.0;
130 if( order >= 3 )
132 if( order == 3 ) angleOffset = 90.0;
133 else angleOffset = 22.5;
135 // Actually draw the cylinders
136 for( int i = 0; i < order; i++)
138 double alpha = angleOffset / 180.0 * M_PI + 2.0 * M_PI * i / order;
139 Vector3d displacement = cos(alpha) * ortho1 + sin(alpha) * ortho2;
140 Vector3d displacedEnd1 = end1 + displacement;
141 Vector3d displacedEnd2 = end2 + displacement;
142 // Write out a POVRay cylinder for rendering
143 *(d->output) << "cylinder {\n"
144 << "\t<" << displacedEnd1.x() << ", "
145 << displacedEnd1.y() << ", "
146 << displacedEnd1.z() << ">, "
147 << "\t<" << displacedEnd2.x() << ", "
148 << displacedEnd2.y() << ", "
149 << displacedEnd2.z() << ">, " << radius
150 << "\n\tpigment { rgbf <" << d->color.red() << ", " << d->color.green() << ", "
151 << d->color.blue() << ", " << 1.0 - d->color.alpha() << "> }\n}\n";
156 void POVPainter::drawShadedSector(Eigen::Vector3d, Eigen::Vector3d,
157 Eigen::Vector3d, double, bool)
161 void POVPainter::drawArc(Eigen::Vector3d, Eigen::Vector3d, Eigen::Vector3d,
162 double, double, bool)
166 void POVPainter::drawShadedQuadrilateral(Eigen::Vector3d, Eigen::Vector3d,
167 Eigen::Vector3d, Eigen::Vector3d)
171 void POVPainter::drawQuadrilateral(Eigen::Vector3d, Eigen::Vector3d,
172 Eigen::Vector3d, Eigen::Vector3d,
173 double)
177 int POVPainter::drawText (int, int, const QString &) const
179 return 0;
182 int POVPainter::drawText (const QPoint&, const QString &) const
184 return 0;
187 int POVPainter::drawText (const Vector3d &, const QString &) const
189 return 0;
192 void POVPainter::begin(QTextStream *output, Vector3d planeNormalVector)
194 d->output = output;
195 d->planeNormalVector = planeNormalVector;
198 void POVPainter::end()
200 d->output = 0;
203 POVPainterDevice::POVPainterDevice(const QString& filename, const GLWidget* glwidget)
205 m_glwidget = glwidget;
206 m_painter = new POVPainter;
207 m_file = new QFile(filename);
208 if (!m_file->open(QIODevice::WriteOnly | QIODevice::Text))
209 return;
210 m_output = new QTextStream(m_file);
211 m_painter->begin(m_output, m_glwidget->normalVector());
213 m_engines = m_glwidget->engines();
215 initializePOV();
216 render();
219 POVPainterDevice::~POVPainterDevice()
221 m_painter->end();
222 delete m_output;
223 m_output = 0;
224 m_file->close();
225 delete m_file;
228 void POVPainterDevice::initializePOV()
230 // Initialise our POV-Ray scene
231 // The POV-Ray camera basically has the same matrix elements - we just need to translate
232 // FIXME Still working on getting the translation to POV-Ray right...
233 Vector3d cameraT = m_glwidget->camera()->modelview().translationVector();
234 Vector3d cameraX = m_glwidget->camera()->backTransformedXAxis();
235 Vector3d cameraY = m_glwidget->camera()->backTransformedYAxis();
236 Vector3d cameraZ = m_glwidget->camera()->backTransformedZAxis();
237 Vector3d light = cameraT + Vector3d(0.8, 0.7, 1.0);
239 // Output the POV-Ray initialisation code
240 *(m_output) << "global_settings {\n"
241 << "\tambient_light rgb <1,1,1>\n"
242 << "\tmax_trace_level 20\n}\n\n"
243 << "background { color rgb <1,1,1> }\n\n"
244 << "camera {\n"
245 << "\tperspective\n"
246 << "\tlocation <" << cameraT.x() << ", " << cameraT.y() << ", " << cameraT.z() << ">\n"
247 // << "\tright 1.33 * <" << cameraX.x() << ", " << cameraX.y() << ", " << cameraX.z() << ">\n"
248 // << "\tup <" << cameraY.x() << ", " << cameraY.y() << ", " << cameraY.z() << ">\n"
249 // << "\tdirection <" << cameraZ.x() << ", " << cameraZ.y() << ", " << cameraZ.z() << ">\n"
250 << "\tlook_at <0, 0, 0>\n"
251 // << "\tsky y\n}\n\n"
252 << "light_source {\n"
253 << "\t<" << light.x() << ", " << light.y() << ", " << light.z() << ">\n"
254 << "\tcolor rgb<1,1,1>\n"
255 << "}\n\n"
256 << "#default {\n\tfinish {ambient .4 diffuse .6 specular 0.9 roughness .005 metallic}\n}";
259 void POVPainterDevice::render()
261 // Now render the scene using the active engines
262 foreach( Engine *engine, m_engines ) {
263 if ( engine->isEnabled() )
264 engine->renderOpaque(this);
265 if ( engine->isEnabled() && engine->flags() & Engine::Transparent )
266 engine->renderTransparent(this);
271 } // End namespace Avogadro