/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- unit
- angle
1 #include "mesh/CylinderMesh.hpp"
2 #include <osgUtil/SmoothingVisitor>
3
4 CylinderMesh::CylinderMesh()
5 { }
6
7 const tuple< const Vec3Array * const
8 , const DrawElementsUShort * const
9 , const Vec3Array * const
10 >
11 CylinderMesh::unit(unsigned int points)
12 {
13 //points should always be even
14
15 // First check if cylinder with the required number of points already exists.
16 auto result = cylinders.find(points);
17 if(result != cylinders.end()) { return result -> second; }
18
19 // If a cylinder is not found then create, cache and return it.
20
21 unsigned int vertex_count = 2 * points;
22 unsigned int triangle_count = 12 * points - 12;
23
24 unsigned int triangle_index = 0;
25
26 unsigned int i, j;
27 float theta;
28
29 float theta_delta = 2.0 * M_PI / points;
30 float z;
31 float radius;
32
33 Vec3Array * vertices = new Vec3Array(2 * vertex_count);
34 Vec3Array * normals = new Vec3Array(2 * vertex_count);
35 DrawElementsUShort * indices = new DrawElementsUShort(GL_TRIANGLES, triangle_count);
36
37 float x, y;
38 // const float COS_DELTA_THETA = cos(theta_delta);
39 // const float COS_DELTA_THETA_HALF = cos(theta_delta / 2);
40 // const float NORMAL_MAGNITUDE = sqrt(COS_DELTA_THETA + 3);
41 // float x, y, nx, ny;
42 // const float NZ = M_SQRT2 / NORMAL_MAGNITUDE;
43 // const float NC = M_SQRT2 * COS_DELTA_THETA_HALF / NORMAL_MAGNITUDE;
44
45 for(i = 0; i < points; ++i)
46 {
47 theta = i * theta_delta;
48 x = cos(theta);
49 y = sin(theta);
50
51 // nx = NC * x;
52 // ny = NC * y;
53
54 (*vertices)[i] = Vec3f(x, y, 0.5f);
55 (*vertices)[i + points] = Vec3f(x, y, -0.5f);
56 (*vertices)[i + 2 * points] = Vec3f(x, y, 0.5f);
57 (*vertices)[i + 3 * points] = Vec3f(x, y, -0.5f);
58
59 // (*normals)[i] = Vec3f(nx, ny, NZ);
60 // (*normals)[i + points] = Vec3f(nx, ny, -NZ);
61 (*normals)[i] = Vec3f(x,y,0.0f);
62 (*normals)[i + points] = Vec3f(x,y,0.0f);
63 (*normals)[i + 2 * points] = Vec3f(0.0f, 0.0f, 1.0f);
64 (*normals)[i + 3 * points] = Vec3f( 0.0f, 0.0f, -1.0f);
65
66 // (*normals)[i + points] -> normalize();
67 // (*normals)[i] = Vec3f(nx, ny, 0);
68 // (*normals)[i + points] = Vec3f(nx, ny, 0);
69 }
70
71 for(i = 0; i < points; ++i)
72 {
73 (*indices)[triangle_index ] = i;
74 (*indices)[triangle_index + 1] = i + points;
75 (*indices)[triangle_index + 2] = i + 1;
76
77 (*indices)[triangle_index + 3] = i + points;
78 (*indices)[triangle_index + 4] = i + 1 + points;
79 (*indices)[triangle_index + 5] = i + 1;
80
81 triangle_index += 6;
82 }
83
84 (*indices)[triangle_index - 1] = 0;
85 (*indices)[triangle_index - 2] = points;
86 (*indices)[triangle_index - 4] = 0;
87
88 for(i = 2 * points + 1; i < 3 * points - 1; ++i)
89 {
90 (*indices)[triangle_index ] = 2 * points;
91 (*indices)[triangle_index + 1] = i;
92 (*indices)[triangle_index + 2] = i + 1;
93 triangle_index += 3;
94 }
95
96 for(i = 3 * points + 1; i < 4 * points - 1; ++i)
97 {
98 (*indices)[triangle_index ] = i + 1;
99 (*indices)[triangle_index + 1] = i;
100 (*indices)[triangle_index + 2] = 3 * points;
101 triangle_index += 3;
102 }
103
104 auto insert_position =
105 cylinders.insert( make_pair( points
106 , make_tuple( vertices
107 , indices
108 , normals
109 )
110 )
111 );
112 return insert_position.first -> second;
113 }
114
115 float
116 CylinderMesh::angle(Vec3f& vector1, Vec3f& vector2)
117 {
118 float dot = vector1 * vector2;
119 float det = vector1.x() * vector2.y() - vector1.y() * vector2.x();
120 RECORD_INFO(string("angle =>") + to_string(atan2(det, dot)));
121 return atan2(det, dot);
122 }
123
124 void
125 CylinderMesh::operator()( Vec3f center
126 , float upper_radius
127 , float lower_radius
128 , float height
129 , Vec3f direction
130 , Geometry * geometry
131 , unsigned int points
132 , const Vec4& color
133 , Vec3f parent
134 )
135 {
136 const auto arrays = unit(points);
137
138 const auto unit_vertices = get<0>(arrays);
139 const auto unit_indices = get<1>(arrays);
140 const auto unit_normals = get<2>(arrays);
141
142 ref_ptr<Vec3Array> vertices(
143 new Vec3Array(unit_vertices -> size())
144 );
145 ref_ptr<Vec3Array> normals(
146 new Vec3Array(unit_normals -> size())
147 );
148 ref_ptr<DrawElementsUShort> indices(
149 new DrawElementsUShort(*unit_indices)
150 );
151
152 unsigned int i, j;
153 Vec3f temp_vertex;
154
155
156
157 Quat rotate;
158 rotate.makeRotate(parent, osg::Vec3f(0.0f, 0.0f, 1.0f));
159 Vec3f side = osg::Vec3f(0.0f, 0.0f, 1.0f) ^ (rotate * direction);
160 side.normalize();
161 RECORD_INFO(string("side => ") + to_string(side[0]) + "," + to_string(side[1]) + "," + to_string(side[2]));
162
163 float warp_angle = acos((parent * direction) / (parent.length() * direction.length()));
164
165 float max_warp = lower_radius * tan(warp_angle);
166
167 RECORD_INFO(to_string(warp_angle));
168 // RECORD_INFO();
169 if(parent.length() != 0.0)
170 {
171 RECORD_INFO("coming here!");
172 for(i = 0; i < points; ++i)
173 {
174 temp_vertex.set( (*vertices)[i + points][0]
175 , (*vertices)[i + points][1]
176 , 0.0
177 );
178 float proportion = angle(side, temp_vertex) / M_PI;
179 RECORD_INFO( string("proportion => ") + to_string(proportion));
180 if(proportion <= -0.5f)
181 {
182 (*vertices)[i + 3 * points][2] = (*vertices)[i + points][2] =
183 -0.5 - 2 * (1 + proportion) * max_warp;
184 }
185 else if(proportion <= 0.0f)
186 {
187 (*vertices)[i + 3 * points][2] = (*vertices)[i + points][2] =
188 -0.5 + 2 * proportion * max_warp;
189 }
190 else if(proportion <= 0.5f)
191 {
192 (*vertices)[i + 3 * points][2] = (*vertices)[i + points][2] =
193 -0.5 + 2 * proportion * max_warp;
194 }
195 else if(proportion <= 1.0f)
196 {
197 (*vertices)[i + 3 * points][2] = (*vertices)[i + points][2] =
198 -0.5 + 2 * (1.0 - proportion) * max_warp;
199 }
200 }
201 }
202
203 rotate.makeRotate(osg::Vec3f(0.0f, 0.0f, 1.0f), direction);
204
205 for(i = 0; i < points; ++i)
206 {
207 temp_vertex.set( upper_radius * (*unit_vertices)[i][0]
208 , upper_radius * (*unit_vertices)[i][1]
209 , height/2.0f
210 );
211 (*vertices)[i + 2 * points] = (*vertices)[i] = rotate * temp_vertex + center;
212 (*normals)[i + points] = (*normals)[i] = rotate * (*unit_normals)[i];
213 (*normals)[i + 2 * points] = direction;
214 (*normals)[i + 3 * points] = -direction;
215 j = i + points;
216 temp_vertex.set( lower_radius * (*unit_vertices)[j][0]
217 , lower_radius * (*unit_vertices)[j][1]
218 , -height/2.0f
219 );
220
221 (*vertices)[j + 2 * points] = (*vertices)[j] = rotate * temp_vertex + center;
222 }
223
224
225 // for(; i < unit_vertices -> size(); ++i)
226 // {
227 // (*vertices)[i] = rotate * temp_vertex + center;
228
229 // (*normals)[i] = rotate * (*unit_normals)[i];
230 // }
231
232 Vec4Array * colors = new Vec4Array();
233 colors -> push_back(color); //color);
234 // for(i = 0; i < vertices -> size(); ++i)
235 // {
236 // }
237 geometry -> setNormalArray( normals.get()
238 , Array::BIND_PER_VERTEX
239 );
240 // polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,6));
241 geometry -> addPrimitiveSet(indices.get());
242 geometry -> setVertexArray(vertices.get());
243 geometry -> setColorArray(colors);
244 geometry -> setColorBinding( osg::Geometry::BIND_OVERALL );
245 // osgUtil::SmoothingVisitor::smooth(*geometry);
246 }
247
248 Geometry *
249 CylinderMesh::operator()( Vec3f center
250 , float upper_radius
251 , float lower_radius
252 , float height
253 , Vec3f direction
254 , unsigned int points
255 , const Vec4& color
256 , Vec3f parent
257 )
258 {
259
260 Geometry * geometry = new Geometry();
261 operator()( center
262 , upper_radius
263 , lower_radius
264 , height
265 , direction
266 , geometry
267 , points
268 , color
269 , parent
270 );
271 return geometry;
272 }
273
274
275 void
276 CylinderMesh::operator()( Vec4f upper
277 , Vec4f lower
278 , Geometry * geometry
279 , unsigned int points
280 , const Vec4& color
281 , Vec3f parent
282 )
283 {
284 Vec3f center( (upper[0] + lower[0]) / 2.0
285 , (upper[1] + lower[1]) / 2.0
286 , (upper[2] + lower[2]) / 2.0
287 );
288
289 Vec3f direction( upper[0] - lower[0]
290 , upper[1] - lower[1]
291 , upper[2] - lower[2]
292 );
293
294 float height = direction.normalize();
295 float upper_radius = upper[3];
296 float lower_radius = lower[3];
297
298 operator()( center
299 , upper_radius
300 , lower_radius
301 , height
302 , direction
303 , geometry
304 , points
305 , color
306 , parent
307 );
308 }
309
310 Geometry *
311 CylinderMesh::operator()( Vec4f upper
312 , Vec4f lower
313 , unsigned int points
314 , const Vec4& color
315 , Vec3f parent
316 )
317 {
318 Geometry * geometry = new Geometry();
319 operator()( upper
320 , lower
321 , geometry
322 , points
323 , color
324 , parent
325 );
326 return geometry;
327 }