1 /******************************************************************************
2 
3   This source file is part of the Avogadro project.
4 
5   Copyright 2017 Kitware, Inc.
6 
7   This source code is released under the New BSD License, (the "License").
8 
9   Unless required by applicable law or agreed to in writing, software
10   distributed under the License is distributed on an "AS IS" BASIS,
11   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   See the License for the specific language governing permissions and
13   limitations under the License.
14 
15 ******************************************************************************/
16 
17 #include "vrmlvisitor.h"
18 
19 #include "ambientocclusionspheregeometry.h"
20 #include "cylindergeometry.h"
21 #include "linestripgeometry.h"
22 #include "meshgeometry.h"
23 #include "spheregeometry.h"
24 
25 #include <iostream>
26 #include <ostream>
27 
28 namespace Avogadro {
29 namespace Rendering {
30 
31 using std::cout;
32 using std::string;
33 using std::endl;
34 using std::ostringstream;
35 using std::ostream;
36 using std::ofstream;
37 
38 namespace {
operator <<(ostream & os,const Vector3f & v)39 ostream& operator<<(ostream& os, const Vector3f& v)
40 {
41   os << v[0] << " " << v[1] << " " << v[2];
42   return os;
43 }
44 
operator <<(ostream & os,const Vector3ub & color)45 ostream& operator<<(ostream& os, const Vector3ub& color)
46 {
47   os << color[0] / 255.0f << "\t" << color[1] / 255.0f << "\t"
48      << color[2] / 255.0f;
49   return os;
50 }
51 
operator <<(ostream & os,const Vector4ub & color)52 ostream& operator<<(ostream& os, const Vector4ub& color)
53 {
54   os << color[0] / 255.0f << " " << color[1] / 255.0f << " "
55      << color[2] / 255.0f << color[3] / 255.0f;
56   return os;
57 }
58 }
59 
VRMLVisitor(const Camera & c)60 VRMLVisitor::VRMLVisitor(const Camera& c)
61   : m_camera(c), m_backgroundColor(255, 255, 255),
62     m_ambientColor(100, 100, 100), m_aspectRatio(800.0f / 600.0f)
63 {
64 }
65 
~VRMLVisitor()66 VRMLVisitor::~VRMLVisitor()
67 {
68 }
69 
begin()70 void VRMLVisitor::begin()
71 {
72 
73   // Initialise the VRML scene
74   Vector3f cameraT = -(m_camera.modelView().linear().adjoint() *
75                        m_camera.modelView().translation());
76   Vector3f cameraX =
77     m_camera.modelView().linear().row(0).transpose().normalized();
78   Vector3f cameraY =
79     m_camera.modelView().linear().row(1).transpose().normalized();
80   Vector3f cameraZ =
81     -m_camera.modelView().linear().row(2).transpose().normalized();
82 
83   double huge = 100;
84 
85   Vector3f light0pos =
86     huge * (m_camera.modelView().linear().adjoint() * Vector3f(0, 1, 0));
87 
88   // Output the POV-Ray initialisation code
89   // orientation should be set
90   // http://cgvr.informatik.uni-bremen.de/teaching/vr_literatur/Calculating%20VRML%20Viewpoints.html
91   ostringstream str;
92   str << "#VRML V2.0 utf8\n"
93       << "DEF DefaultView Viewpoint {\n"
94       << "position " << cameraT << " \n"
95       << "fieldOfView 0.785398\n}\n";
96 
97   m_sceneData = str.str();
98 }
99 
end()100 string VRMLVisitor::end()
101 {
102   return m_sceneData;
103 }
104 
visit(Drawable & geometry)105 void VRMLVisitor::visit(Drawable& geometry)
106 {
107   // geometry.render(m_camera);
108 }
109 
visit(SphereGeometry & geometry)110 void VRMLVisitor::visit(SphereGeometry& geometry)
111 {
112   ostringstream str;
113   for (size_t i = 0; i < geometry.spheres().size(); ++i) {
114     Rendering::SphereColor s = geometry.spheres()[i];
115 
116     str << "Transform {\n"
117         << "\ttranslation\t" << s.center[0] << "\t" << s.center[1] << "\t"
118         << s.center[2] << "\n\tchildren Shape {\n"
119         << "\t\tgeometry Sphere {\n\t\t\tradius\t" << s.radius << "\n\t\t}\n"
120         << "\t\tappearance Appearance {\n"
121         << "\t\t\tmaterial Material {\n"
122         << "\t\t\t\tdiffuseColor\t" << s.color << "\n\t\t\t}\n\t\t}\n\t}\n}\n";
123   }
124   m_sceneData += str.str();
125 }
126 
visit(AmbientOcclusionSphereGeometry & geometry)127 void VRMLVisitor::visit(AmbientOcclusionSphereGeometry& geometry)
128 {
129   // geometry.render(m_camera);
130 }
131 
visit(CylinderGeometry & geometry)132 void VRMLVisitor::visit(CylinderGeometry& geometry)
133 {
134   ostringstream str;
135   for (size_t i = 0; i < geometry.cylinders().size(); ++i) {
136     Rendering::CylinderColor c = geometry.cylinders()[i];
137 
138     // double scale = 1.0;
139     double x1, x2, y1, y2, z1, z2;
140     x1 = c.end1[0];
141     x2 = c.end2[0];
142     y1 = c.end1[1];
143     y2 = c.end2[1];
144     z1 = c.end1[2];
145     z2 = c.end2[2];
146 
147     double dx = x2 - x1;
148     double dy = y2 - y1;
149     double dz = z2 - z1;
150 
151     double length = sqrt(dx * dx + dy * dy + dz * dz);
152     double tx = dx / 2 + x1;
153     double ty = dy / 2 + y1;
154     double tz = dz / 2 + z1;
155 
156     dx = dx / length;
157     dy = dy / length;
158     dz = dz / length;
159 
160     double ax, ay, az, angle;
161 
162     if (dy > 0.999) {
163       ax = 1.0;
164       ay = 0.0;
165       az = 0.0;
166       angle = 0.0;
167     } else if (dy < -0.999) {
168       ax = 1.0;
169       ay = 0.0;
170       az = 0.0;
171       angle = 3.14159265359;
172     } else {
173       ax = dz;
174       ay = 0.0;
175       az = dx * -1.0;
176       angle = acos(dy);
177     }
178     length = length / 2.0;
179 
180     str << "Transform {\n"
181         << "\ttranslation\t" << tx << "\t" << ty << "\t" << tz << "\n\tscale "
182         << " 1 " << length << " 1"
183         << "\n\trotation " << ax << " " << ay << " " << az << " " << angle
184         << "\n\tchildren Shape {\n"
185         << "\t\tgeometry Cylinder {\n\t\t\tradius\t" << c.radius << "\n\t\t}\n"
186         << "\t\tappearance Appearance {\n"
187         << "\t\t\tmaterial Material {\n"
188         << "\t\t\t\tdiffuseColor\t" << c.color << "\n\t\t\t}\n\t\t}\n\t}\n}\n";
189   }
190   m_sceneData += str.str();
191 }
192 
visit(MeshGeometry & geometry)193 void VRMLVisitor::visit(MeshGeometry& geometry)
194 {
195   Core::Array<Rendering::MeshGeometry::PackedVertex> v = geometry.vertices();
196 
197   // If there are no triangles then don't bother doing anything
198   if (v.size() == 0)
199     return;
200 
201   ostringstream str, verts, iverts, colors;
202 
203   // save the points, coordinates, and colors to separate strings
204   for (unsigned int i = 0; i < v.size(); ++i) {
205     if (i == v.size() - 1) {
206       verts << v[i].vertex;
207       colors << v[i].color;
208       break;
209     }
210     verts << v[i].vertex << ",\n";
211     colors << v[i].color << ", ";
212   }
213   // Now to write out the indices
214   for (unsigned int i = 0; i < v.size(); i += 3) {
215     iverts << i << ", " << i + 1 << ", " << i + 2 << ", -1,\n";
216   }
217 
218   // Now to write out the full mesh - could be pretty big...
219   str << "Shape {\n"
220       << "\tgeometry IndexedFaceSet {\n"
221       << "\t\tcoord Coordinate {\n"
222       << "\t\t\tpoint [" << verts.str() << "\t\t\t]\n\t\t}\n"
223       << "\t\tcoordIndex[" << iverts.str() << "\t\t\t]\n"
224       << "color Color {\n color [" << colors.str() << "]\n}\n}\n}";
225 
226   m_sceneData += str.str();
227 }
228 
visit(LineStripGeometry & geometry)229 void VRMLVisitor::visit(LineStripGeometry& geometry)
230 {
231   // geometry.render(m_camera);
232 }
233 
234 } // End namespace Rendering
235 } // End namespace Avogadro
236