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