1 | /* |
2 | Open Asset Import Library (assimp) |
3 | ---------------------------------------------------------------------- |
4 | |
5 | Copyright (c) 2006-2017, assimp team |
6 | |
7 | All rights reserved. |
8 | |
9 | Redistribution and use of this software in source and binary forms, |
10 | with or without modification, are permitted provided that the |
11 | following conditions are met: |
12 | |
13 | * Redistributions of source code must retain the above |
14 | copyright notice, this list of conditions and the |
15 | following disclaimer. |
16 | |
17 | * Redistributions in binary form must reproduce the above |
18 | copyright notice, this list of conditions and the |
19 | following disclaimer in the documentation and/or other |
20 | materials provided with the distribution. |
21 | |
22 | * Neither the name of the assimp team, nor the names of its |
23 | contributors may be used to endorse or promote products |
24 | derived from this software without specific prior |
25 | written permission of the assimp team. |
26 | |
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
28 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
29 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
30 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
31 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
32 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
33 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
34 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
35 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
36 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
37 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
38 | |
39 | ---------------------------------------------------------------------- |
40 | */ |
41 | |
42 | /** @file StandardShapes.cpp |
43 | * @brief Implementation of the StandardShapes class |
44 | * |
45 | * The primitive geometry data comes from |
46 | * http://geometrictools.com/Documentation/PlatonicSolids.pdf. |
47 | */ |
48 | |
49 | #include "StandardShapes.h" |
50 | #include "StringComparison.h" |
51 | #include <stddef.h> |
52 | #include <assimp/Defines.h> |
53 | #include <assimp/mesh.h> |
54 | |
55 | namespace Assimp { |
56 | |
57 | |
58 | # define ADD_TRIANGLE(n0,n1,n2) \ |
59 | positions.push_back(n0); \ |
60 | positions.push_back(n1); \ |
61 | positions.push_back(n2); |
62 | |
63 | # define ADD_PENTAGON(n0,n1,n2,n3,n4) \ |
64 | if (polygons) \ |
65 | { \ |
66 | positions.push_back(n0); \ |
67 | positions.push_back(n1); \ |
68 | positions.push_back(n2); \ |
69 | positions.push_back(n3); \ |
70 | positions.push_back(n4); \ |
71 | } \ |
72 | else \ |
73 | { \ |
74 | ADD_TRIANGLE(n0, n1, n2) \ |
75 | ADD_TRIANGLE(n0, n2, n3) \ |
76 | ADD_TRIANGLE(n0, n3, n4) \ |
77 | } |
78 | |
79 | # define ADD_QUAD(n0,n1,n2,n3) \ |
80 | if (polygons) \ |
81 | { \ |
82 | positions.push_back(n0); \ |
83 | positions.push_back(n1); \ |
84 | positions.push_back(n2); \ |
85 | positions.push_back(n3); \ |
86 | } \ |
87 | else \ |
88 | { \ |
89 | ADD_TRIANGLE(n0, n1, n2) \ |
90 | ADD_TRIANGLE(n0, n2, n3) \ |
91 | } |
92 | |
93 | |
94 | // ------------------------------------------------------------------------------------------------ |
95 | // Fast subdivision for a mesh whose verts have a magnitude of 1 |
96 | void Subdivide(std::vector<aiVector3D>& positions) |
97 | { |
98 | // assume this to be constant - (fixme: must be 1.0? I think so) |
99 | const ai_real fl1 = positions[0].Length(); |
100 | |
101 | unsigned int origSize = (unsigned int)positions.size(); |
102 | for (unsigned int i = 0 ; i < origSize ; i+=3) |
103 | { |
104 | aiVector3D& tv0 = positions[i]; |
105 | aiVector3D& tv1 = positions[i+1]; |
106 | aiVector3D& tv2 = positions[i+2]; |
107 | |
108 | aiVector3D a = tv0, b = tv1, c = tv2; |
109 | aiVector3D v1 = aiVector3D(a.x+b.x, a.y+b.y, a.z+b.z).Normalize()*fl1; |
110 | aiVector3D v2 = aiVector3D(a.x+c.x, a.y+c.y, a.z+c.z).Normalize()*fl1; |
111 | aiVector3D v3 = aiVector3D(b.x+c.x, b.y+c.y, b.z+c.z).Normalize()*fl1; |
112 | |
113 | tv0 = v1; tv1 = v3; tv2 = v2; // overwrite the original |
114 | ADD_TRIANGLE(v1, v2, a); |
115 | ADD_TRIANGLE(v2, v3, c); |
116 | ADD_TRIANGLE(v3, v1, b); |
117 | } |
118 | } |
119 | |
120 | // ------------------------------------------------------------------------------------------------ |
121 | // Construct a mesh from given vertex positions |
122 | aiMesh* StandardShapes::MakeMesh(const std::vector<aiVector3D>& positions, |
123 | unsigned int numIndices) |
124 | { |
125 | if (positions.empty() || !numIndices) return NULL; |
126 | |
127 | // Determine which kinds of primitives the mesh consists of |
128 | aiMesh* out = new aiMesh(); |
129 | switch (numIndices) |
130 | { |
131 | case 1: |
132 | out->mPrimitiveTypes = aiPrimitiveType_POINT; |
133 | break; |
134 | case 2: |
135 | out->mPrimitiveTypes = aiPrimitiveType_LINE; |
136 | break; |
137 | case 3: |
138 | out->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; |
139 | break; |
140 | default: |
141 | out->mPrimitiveTypes = aiPrimitiveType_POLYGON; |
142 | break; |
143 | }; |
144 | |
145 | out->mNumFaces = (unsigned int)positions.size() / numIndices; |
146 | out->mFaces = new aiFace[out->mNumFaces]; |
147 | for (unsigned int i = 0, a = 0; i < out->mNumFaces;++i) |
148 | { |
149 | aiFace& f = out->mFaces[i]; |
150 | f.mNumIndices = numIndices; |
151 | f.mIndices = new unsigned int[numIndices]; |
152 | for (unsigned int i = 0; i < numIndices;++i,++a) |
153 | f.mIndices[i] = a; |
154 | } |
155 | out->mNumVertices = (unsigned int)positions.size(); |
156 | out->mVertices = new aiVector3D[out->mNumVertices]; |
157 | ::memcpy(out->mVertices,&positions[0],out->mNumVertices*sizeof(aiVector3D)); |
158 | return out; |
159 | } |
160 | |
161 | // ------------------------------------------------------------------------------------------------ |
162 | // Construct a mesh with a specific shape (callback) |
163 | aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)( |
164 | std::vector<aiVector3D>&)) |
165 | { |
166 | std::vector<aiVector3D> temp; |
167 | unsigned num = (*GenerateFunc)(temp); |
168 | return MakeMesh(temp,num); |
169 | } |
170 | |
171 | // ------------------------------------------------------------------------------------------------ |
172 | // Construct a mesh with a specific shape (callback) |
173 | aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)( |
174 | std::vector<aiVector3D>&, bool)) |
175 | { |
176 | std::vector<aiVector3D> temp; |
177 | unsigned num = (*GenerateFunc)(temp,true); |
178 | return MakeMesh(temp,num); |
179 | } |
180 | |
181 | // ------------------------------------------------------------------------------------------------ |
182 | // Construct a mesh with a specific shape (callback) |
183 | aiMesh* StandardShapes::MakeMesh (unsigned int num, void (*GenerateFunc)( |
184 | unsigned int,std::vector<aiVector3D>&)) |
185 | { |
186 | std::vector<aiVector3D> temp; |
187 | (*GenerateFunc)(num,temp); |
188 | return MakeMesh(temp,3); |
189 | } |
190 | |
191 | // ------------------------------------------------------------------------------------------------ |
192 | // Build an incosahedron with points.magnitude == 1 |
193 | unsigned int StandardShapes::MakeIcosahedron(std::vector<aiVector3D>& positions) |
194 | { |
195 | positions.reserve(positions.size()+60); |
196 | |
197 | const ai_real t = ( ai_real( 1.0 )+ ai_real( 2.236067977 ) ) / ai_real( 2.0 ); |
198 | const ai_real s = std::sqrt(ai_real(1.0) + t*t); |
199 | |
200 | const aiVector3D v0 = aiVector3D(t,1.0, 0.0)/s; |
201 | const aiVector3D v1 = aiVector3D(-t,1.0, 0.0)/s; |
202 | const aiVector3D v2 = aiVector3D(t,-1.0, 0.0)/s; |
203 | const aiVector3D v3 = aiVector3D(-t,-1.0, 0.0)/s; |
204 | const aiVector3D v4 = aiVector3D(1.0, 0.0, t)/s; |
205 | const aiVector3D v5 = aiVector3D(1.0, 0.0,-t)/s; |
206 | const aiVector3D v6 = aiVector3D(-1.0, 0.0,t)/s; |
207 | const aiVector3D v7 = aiVector3D(-1.0, 0.0,-t)/s; |
208 | const aiVector3D v8 = aiVector3D(0.0, t, 1.0)/s; |
209 | const aiVector3D v9 = aiVector3D(0.0,-t, 1.0)/s; |
210 | const aiVector3D v10 = aiVector3D(0.0, t,-1.0)/s; |
211 | const aiVector3D v11 = aiVector3D(0.0,-t,-1.0)/s; |
212 | |
213 | ADD_TRIANGLE(v0,v8,v4); |
214 | ADD_TRIANGLE(v0,v5,v10); |
215 | ADD_TRIANGLE(v2,v4,v9); |
216 | ADD_TRIANGLE(v2,v11,v5); |
217 | |
218 | ADD_TRIANGLE(v1,v6,v8); |
219 | ADD_TRIANGLE(v1,v10,v7); |
220 | ADD_TRIANGLE(v3,v9,v6); |
221 | ADD_TRIANGLE(v3,v7,v11); |
222 | |
223 | ADD_TRIANGLE(v0,v10,v8); |
224 | ADD_TRIANGLE(v1,v8,v10); |
225 | ADD_TRIANGLE(v2,v9,v11); |
226 | ADD_TRIANGLE(v3,v11,v9); |
227 | |
228 | ADD_TRIANGLE(v4,v2,v0); |
229 | ADD_TRIANGLE(v5,v0,v2); |
230 | ADD_TRIANGLE(v6,v1,v3); |
231 | ADD_TRIANGLE(v7,v3,v1); |
232 | |
233 | ADD_TRIANGLE(v8,v6,v4); |
234 | ADD_TRIANGLE(v9,v4,v6); |
235 | ADD_TRIANGLE(v10,v5,v7); |
236 | ADD_TRIANGLE(v11,v7,v5); |
237 | return 3; |
238 | } |
239 | |
240 | // ------------------------------------------------------------------------------------------------ |
241 | // Build a dodecahedron with points.magnitude == 1 |
242 | unsigned int StandardShapes::MakeDodecahedron(std::vector<aiVector3D>& positions, |
243 | bool polygons /*= false*/) |
244 | { |
245 | positions.reserve(positions.size()+108); |
246 | |
247 | const ai_real a = ai_real( 1.0 ) / ai_real(1.7320508); |
248 | const ai_real b = std::sqrt(( ai_real( 3.0 )- ai_real( 2.23606797))/ ai_real( 6.0) ); |
249 | const ai_real c = std::sqrt(( ai_real( 3.0 )+ ai_real( 2.23606797f))/ ai_real( 6.0) ); |
250 | |
251 | const aiVector3D v0 = aiVector3D(a,a,a); |
252 | const aiVector3D v1 = aiVector3D(a,a,-a); |
253 | const aiVector3D v2 = aiVector3D(a,-a,a); |
254 | const aiVector3D v3 = aiVector3D(a,-a,-a); |
255 | const aiVector3D v4 = aiVector3D(-a,a,a); |
256 | const aiVector3D v5 = aiVector3D(-a,a,-a); |
257 | const aiVector3D v6 = aiVector3D(-a,-a,a); |
258 | const aiVector3D v7 = aiVector3D(-a,-a,-a); |
259 | const aiVector3D v8 = aiVector3D(b,c,0.0); |
260 | const aiVector3D v9 = aiVector3D(-b,c,0.0); |
261 | const aiVector3D v10 = aiVector3D(b,-c,0.0); |
262 | const aiVector3D v11 = aiVector3D(-b,-c,0.0); |
263 | const aiVector3D v12 = aiVector3D(c, 0.0, b); |
264 | const aiVector3D v13 = aiVector3D(c, 0.0, -b); |
265 | const aiVector3D v14 = aiVector3D(-c, 0.0, b); |
266 | const aiVector3D v15 = aiVector3D(-c, 0.0, -b); |
267 | const aiVector3D v16 = aiVector3D(0.0, b, c); |
268 | const aiVector3D v17 = aiVector3D(0.0, -b, c); |
269 | const aiVector3D v18 = aiVector3D(0.0, b, -c); |
270 | const aiVector3D v19 = aiVector3D(0.0, -b, -c); |
271 | |
272 | ADD_PENTAGON(v0, v8, v9, v4, v16); |
273 | ADD_PENTAGON(v0, v12, v13, v1, v8); |
274 | ADD_PENTAGON(v0, v16, v17, v2, v12); |
275 | ADD_PENTAGON(v8, v1, v18, v5, v9); |
276 | ADD_PENTAGON(v12, v2, v10, v3, v13); |
277 | ADD_PENTAGON(v16, v4, v14, v6, v17); |
278 | ADD_PENTAGON(v9, v5, v15, v14, v4); |
279 | |
280 | ADD_PENTAGON(v6, v11, v10, v2, v17); |
281 | ADD_PENTAGON(v3, v19, v18, v1, v13); |
282 | ADD_PENTAGON(v7, v15, v5, v18, v19); |
283 | ADD_PENTAGON(v7, v11, v6, v14, v15); |
284 | ADD_PENTAGON(v7, v19, v3, v10, v11); |
285 | return (polygons ? 5 : 3); |
286 | } |
287 | |
288 | // ------------------------------------------------------------------------------------------------ |
289 | // Build an octahedron with points.magnitude == 1 |
290 | unsigned int StandardShapes::MakeOctahedron(std::vector<aiVector3D>& positions) |
291 | { |
292 | positions.reserve(positions.size()+24); |
293 | |
294 | const aiVector3D v0 = aiVector3D(1.0, 0.0, 0.0) ; |
295 | const aiVector3D v1 = aiVector3D(-1.0, 0.0, 0.0); |
296 | const aiVector3D v2 = aiVector3D(0.0, 1.0, 0.0); |
297 | const aiVector3D v3 = aiVector3D(0.0, -1.0, 0.0); |
298 | const aiVector3D v4 = aiVector3D(0.0, 0.0, 1.0); |
299 | const aiVector3D v5 = aiVector3D(0.0, 0.0, -1.0); |
300 | |
301 | ADD_TRIANGLE(v4,v0,v2); |
302 | ADD_TRIANGLE(v4,v2,v1); |
303 | ADD_TRIANGLE(v4,v1,v3); |
304 | ADD_TRIANGLE(v4,v3,v0); |
305 | |
306 | ADD_TRIANGLE(v5,v2,v0); |
307 | ADD_TRIANGLE(v5,v1,v2); |
308 | ADD_TRIANGLE(v5,v3,v1); |
309 | ADD_TRIANGLE(v5,v0,v3); |
310 | return 3; |
311 | } |
312 | |
313 | // ------------------------------------------------------------------------------------------------ |
314 | // Build a tetrahedron with points.magnitude == 1 |
315 | unsigned int StandardShapes::MakeTetrahedron(std::vector<aiVector3D>& positions) |
316 | { |
317 | positions.reserve(positions.size()+9); |
318 | |
319 | const ai_real invThree = ai_real( 1.0 ) / ai_real( 3.0 ); |
320 | const ai_real a = ai_real( 1.41421 ) * invThree; |
321 | const ai_real b = ai_real( 2.4494 ) * invThree; |
322 | |
323 | const aiVector3D v0 = aiVector3D(0.0,0.0,1.0); |
324 | const aiVector3D v1 = aiVector3D(2*a,0,-invThree ); |
325 | const aiVector3D v2 = aiVector3D(-a,b,-invThree ); |
326 | const aiVector3D v3 = aiVector3D(-a,-b,-invThree ); |
327 | |
328 | ADD_TRIANGLE(v0,v1,v2); |
329 | ADD_TRIANGLE(v0,v2,v3); |
330 | ADD_TRIANGLE(v0,v3,v1); |
331 | ADD_TRIANGLE(v1,v3,v2); |
332 | return 3; |
333 | } |
334 | |
335 | // ------------------------------------------------------------------------------------------------ |
336 | // Build a hexahedron with points.magnitude == 1 |
337 | unsigned int StandardShapes::MakeHexahedron(std::vector<aiVector3D>& positions, |
338 | bool polygons /*= false*/) |
339 | { |
340 | positions.reserve(positions.size()+36); |
341 | const ai_real length = ai_real(1.0)/ai_real(1.73205080); |
342 | |
343 | const aiVector3D v0 = aiVector3D(-1.0,-1.0,-1.0)*length; |
344 | const aiVector3D v1 = aiVector3D(1.0,-1.0,-1.0)*length; |
345 | const aiVector3D v2 = aiVector3D(1.0,1.0,-1.0)*length; |
346 | const aiVector3D v3 = aiVector3D(-1.0,1.0,-1.0)*length; |
347 | const aiVector3D v4 = aiVector3D(-1.0,-1.0,1.0)*length; |
348 | const aiVector3D v5 = aiVector3D(1.0,-1.0,1.0)*length; |
349 | const aiVector3D v6 = aiVector3D(1.0,1.0,1.0)*length; |
350 | const aiVector3D v7 = aiVector3D(-1.0,1.0,1.0)*length; |
351 | |
352 | ADD_QUAD(v0,v3,v2,v1); |
353 | ADD_QUAD(v0,v1,v5,v4); |
354 | ADD_QUAD(v0,v4,v7,v3); |
355 | ADD_QUAD(v6,v5,v1,v2); |
356 | ADD_QUAD(v6,v2,v3,v7); |
357 | ADD_QUAD(v6,v7,v4,v5); |
358 | return (polygons ? 4 : 3); |
359 | } |
360 | |
361 | // Cleanup ... |
362 | #undef ADD_TRIANGLE |
363 | #undef ADD_QUAD |
364 | #undef ADD_PENTAGON |
365 | |
366 | // ------------------------------------------------------------------------------------------------ |
367 | // Create a subdivision sphere |
368 | void StandardShapes::MakeSphere(unsigned int tess, |
369 | std::vector<aiVector3D>& positions) |
370 | { |
371 | // Reserve enough storage. Every subdivision |
372 | // splits each triangle in 4, the icosahedron consists of 60 verts |
373 | positions.reserve(positions.size()+60 * integer_pow(4, tess)); |
374 | |
375 | // Construct an icosahedron to start with |
376 | MakeIcosahedron(positions); |
377 | |
378 | // ... and subdivide it until the requested output |
379 | // tesselation is reached |
380 | for (unsigned int i = 0; i<tess;++i) |
381 | Subdivide(positions); |
382 | } |
383 | |
384 | // ------------------------------------------------------------------------------------------------ |
385 | // Build a cone |
386 | void StandardShapes::MakeCone(ai_real height,ai_real radius1, |
387 | ai_real radius2,unsigned int tess, |
388 | std::vector<aiVector3D>& positions,bool bOpen /*= false */) |
389 | { |
390 | // Sorry, a cone with less than 3 segments makes ABSOLUTELY NO SENSE |
391 | if (tess < 3 || !height) |
392 | return; |
393 | |
394 | size_t old = positions.size(); |
395 | |
396 | // No negative radii |
397 | radius1 = std::fabs(radius1); |
398 | radius2 = std::fabs(radius2); |
399 | |
400 | ai_real halfHeight = height / ai_real(2.0); |
401 | |
402 | // radius1 is always the smaller one |
403 | if (radius2 > radius1) |
404 | { |
405 | std::swap(radius2,radius1); |
406 | halfHeight = -halfHeight; |
407 | } |
408 | else old = SIZE_MAX; |
409 | |
410 | // Use a large epsilon to check whether the cone is pointy |
411 | if (radius1 < (radius2-radius1)*10e-3)radius1 = 0.0; |
412 | |
413 | // We will need 3*2 verts per segment + 3*2 verts per segment |
414 | // if the cone is closed |
415 | const unsigned int mem = tess*6 + (!bOpen ? tess*3 * (radius1 ? 2 : 1) : 0); |
416 | positions.reserve(positions.size () + mem); |
417 | |
418 | // Now construct all segments |
419 | const ai_real angle_delta = (ai_real)AI_MATH_TWO_PI / tess; |
420 | const ai_real angle_max = (ai_real)AI_MATH_TWO_PI; |
421 | |
422 | ai_real s = 1.0; // std::cos(angle == 0); |
423 | ai_real t = 0.0; // std::sin(angle == 0); |
424 | |
425 | for (ai_real angle = 0.0; angle < angle_max; ) |
426 | { |
427 | const aiVector3D v1 = aiVector3D (s * radius1, -halfHeight, t * radius1 ); |
428 | const aiVector3D v2 = aiVector3D (s * radius2, halfHeight, t * radius2 ); |
429 | |
430 | const ai_real next = angle + angle_delta; |
431 | ai_real s2 = std::cos(next); |
432 | ai_real t2 = std::sin(next); |
433 | |
434 | const aiVector3D v3 = aiVector3D (s2 * radius2, halfHeight, t2 * radius2 ); |
435 | const aiVector3D v4 = aiVector3D (s2 * radius1, -halfHeight, t2 * radius1 ); |
436 | |
437 | positions.push_back(v1); |
438 | positions.push_back(v2); |
439 | positions.push_back(v3); |
440 | positions.push_back(v4); |
441 | positions.push_back(v1); |
442 | positions.push_back(v3); |
443 | |
444 | if (!bOpen) |
445 | { |
446 | // generate the end 'cap' |
447 | positions.push_back(aiVector3D(s * radius2, halfHeight, t * radius2 )); |
448 | positions.push_back(aiVector3D(s2 * radius2, halfHeight, t2 * radius2 )); |
449 | positions.push_back(aiVector3D(0.0, halfHeight, 0.0)); |
450 | |
451 | |
452 | if (radius1) |
453 | { |
454 | // generate the other end 'cap' |
455 | positions.push_back(aiVector3D(s * radius1, -halfHeight, t * radius1 )); |
456 | positions.push_back(aiVector3D(s2 * radius1, -halfHeight, t2 * radius1 )); |
457 | positions.push_back(aiVector3D(0.0, -halfHeight, 0.0)); |
458 | |
459 | } |
460 | } |
461 | s = s2; |
462 | t = t2; |
463 | angle = next; |
464 | } |
465 | |
466 | // Need to flip face order? |
467 | if ( SIZE_MAX != old ) { |
468 | for (size_t s = old; s < positions.size();s += 3) { |
469 | std::swap(positions[s],positions[s+1]); |
470 | } |
471 | } |
472 | } |
473 | |
474 | // ------------------------------------------------------------------------------------------------ |
475 | // Build a circle |
476 | void StandardShapes::MakeCircle(ai_real radius, unsigned int tess, |
477 | std::vector<aiVector3D>& positions) |
478 | { |
479 | // Sorry, a circle with less than 3 segments makes ABSOLUTELY NO SENSE |
480 | if (tess < 3 || !radius) |
481 | return; |
482 | |
483 | radius = std::fabs(radius); |
484 | |
485 | // We will need 3 vertices per segment |
486 | positions.reserve(positions.size()+tess*3); |
487 | |
488 | const ai_real angle_delta = (ai_real)AI_MATH_TWO_PI / tess; |
489 | const ai_real angle_max = (ai_real)AI_MATH_TWO_PI; |
490 | |
491 | ai_real s = 1.0; // std::cos(angle == 0); |
492 | ai_real t = 0.0; // std::sin(angle == 0); |
493 | |
494 | for (ai_real angle = 0.0; angle < angle_max; ) |
495 | { |
496 | positions.push_back(aiVector3D(s * radius,0.0,t * radius)); |
497 | angle += angle_delta; |
498 | s = std::cos(angle); |
499 | t = std::sin(angle); |
500 | positions.push_back(aiVector3D(s * radius,0.0,t * radius)); |
501 | |
502 | positions.push_back(aiVector3D(0.0,0.0,0.0)); |
503 | } |
504 | } |
505 | |
506 | } // ! Assimp |
507 | |