SO3Engine
SO3BaseMeshsTools.cpp
Go to the documentation of this file.
1/*
2-----------------------------------------------------------------------------
3This source file is part of OpenSpace3D
4For the latest info, see http://www.openspace3d.com
5
6Copyright (c) 2012 I-maginer
7
8This program is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the Free Software
10Foundation; either version 2 of the License, or (at your option) any later
11version.
12
13This program is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public License along with
18this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20http://www.gnu.org/copyleft/lesser.txt
21
22-----------------------------------------------------------------------------
23*/
24
26
27namespace SO3
28{
29
30SBaseMeshsTools::SBaseMeshsTools()
31{
32 // Forbiden (private). Use static functions instead.
33}
34
35Ogre::MeshPtr SBaseMeshsTools::CreateSphere(const Ogre::String& strName, float radius, int nRings, int nSegments, bool bNormals, bool bTexCoords, Ogre::String groupName)
36{
37 Ogre::MeshPtr pSphere = Ogre::MeshManager::getSingleton().createManual(strName, groupName);
38 Ogre::SubMesh* pSphereVertex = pSphere->createSubMesh();
39 pSphere->sharedVertexData = new Ogre::VertexData();
40 CreateSphere(pSphere->sharedVertexData, pSphereVertex->indexData, radius, nRings, nSegments, bNormals, bTexCoords);
41
42 // Generate face list
43 pSphereVertex->useSharedVertices = true;
44 pSphere->_setBounds(Ogre::AxisAlignedBox(Ogre::Vector3(-radius, -radius, -radius), Ogre::Vector3(radius, radius, radius)), false);
45 pSphere->_setBoundingSphereRadius(radius);
46
47 // this line makes clear the mesh is loaded (avoids memory leaks)
48 pSphere->load();
49 return pSphere;
50}
51
52void SBaseMeshsTools::CreateSphere(Ogre::VertexData*& vertexData, Ogre::IndexData*& indexData, float radius, int nRings, int nSegments, bool bNormals, bool bTexCoords)
53{
54 assert(vertexData && indexData);
55
56 // define the vertex format
57 Ogre::VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
58 size_t currOffset = 0;
59
60 // positions
61 vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
62 currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
63
64 // normals
65 if (bNormals)
66 {
67 vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
68 currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
69 }
70
71 // two dimensional texture coordinates
72 if (bTexCoords)
73 {
74 vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0);
75 currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
76 }
77
78 // allocate the vertex buffer
79 vertexData->vertexCount = (nRings+1) * (nSegments+1);
80 Ogre::HardwareVertexBufferSharedPtr vBuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC, false);
81 Ogre::VertexBufferBinding* binding = vertexData->vertexBufferBinding;
82 binding->setBinding(0, vBuf);
83 float* pVertex = static_cast<float*>(vBuf->lock(Ogre::HardwareBuffer::HBL_WRITE_ONLY));
84
85 // allocate index buffer
86 indexData->indexCount = 6 * nRings * (nSegments+1);
87 indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC, false);
88 Ogre::HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer;
89 unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(Ogre::HardwareBuffer::HBL_WRITE_ONLY));
90
91 float fDeltaRingAngle = (Ogre::Math::PI / nRings);
92 float fDeltaSegAngle = (2 * Ogre::Math::PI / nSegments);
93 unsigned short wVerticeIndex = 0 ;
94
95 // Generate the group of rings for the sphere
96 for(int ring = 0; ring <= nRings; ring++)
97 {
98 float r0 = radius * sinf (ring * fDeltaRingAngle);
99 float y0 = radius * cosf (ring * fDeltaRingAngle);
100
101 // Generate the group of segments for the current ring
102 for(int seg = 0; seg <= nSegments; seg++)
103 {
104 float x0 = r0 * sinf(seg * fDeltaSegAngle);
105 float z0 = r0 * cosf(seg * fDeltaSegAngle);
106
107 // Add one vertex to the strip which makes up the sphere
108 *pVertex++ = x0;
109 *pVertex++ = y0;
110 *pVertex++ = z0;
111
112 if (bNormals)
113 {
114 Ogre::Vector3 vNormal = Ogre::Vector3(x0, y0, z0).normalisedCopy();
115 *pVertex++ = vNormal.x;
116 *pVertex++ = vNormal.y;
117 *pVertex++ = vNormal.z;
118 }
119
120 if (bTexCoords)
121 {
122 *pVertex++ = (float) seg / (float) nSegments;
123 *pVertex++ = (float) ring / (float) nRings;
124 }
125
126 if (ring != nRings)
127 {
128 // each vertex (except the last) has six indices pointing to it
129 *pIndices++ = wVerticeIndex + nSegments + 1;
130 *pIndices++ = wVerticeIndex;
131 *pIndices++ = wVerticeIndex + nSegments;
132 *pIndices++ = wVerticeIndex + nSegments + 1;
133 *pIndices++ = wVerticeIndex + 1;
134 *pIndices++ = wVerticeIndex;
135 wVerticeIndex ++;
136 }
137 }
138 }
139
140 // Unlock
141 vBuf->unlock();
142 iBuf->unlock();
143}
144
145Ogre::MeshPtr SBaseMeshsTools::CreateCone(const Ogre::String& strName , float radius , float height, int nVerticesInBase, Ogre::String groupName)
146{
147 Ogre::MeshPtr pCone = Ogre::MeshManager::getSingleton().createManual(strName, groupName);
148 Ogre::SubMesh *pConeVertex = pCone->createSubMesh();
149 pCone->sharedVertexData = new Ogre::VertexData();
150
151 CreateCone(pCone->sharedVertexData, pConeVertex->indexData, radius, height, nVerticesInBase);
152
153 // Generate face list
154 pConeVertex->useSharedVertices = true;
155 pCone->_setBounds(Ogre::AxisAlignedBox(Ogre::Vector3(-radius, 0, -radius), Ogre::Vector3(radius, height, radius)), false);
156 pCone->_setBoundingSphereRadius(Ogre::Math::Sqrt(height*height + radius*radius));
157
158 // this line makes clear the mesh is loaded (avoids memory leaks)
159 pCone->load();
160
161 return pCone;
162}
163
164void SBaseMeshsTools::CreateCone(Ogre::VertexData*& vertexData, Ogre::IndexData*& indexData, float radius , float height, int nVerticesInBase)
165{
166 assert(vertexData && indexData);
167
168 // define the vertex format
169 Ogre::VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
170
171 size_t currOffset = 0;
172
173 // positions
174 vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
175 currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
176
177 // normals
178 vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
179 currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
180
181 // two dimensional texture coordinates
182 vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0);
183 currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
184
185 // allocate the vertex buffer
186 vertexData->vertexCount = nVerticesInBase + 1;
187 Ogre::HardwareVertexBufferSharedPtr vBuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC, false);
188 Ogre::VertexBufferBinding* binding = vertexData->vertexBufferBinding;
189 binding->setBinding(0, vBuf);
190 float* pVertex = static_cast<float*>(vBuf->lock(Ogre::HardwareBuffer::HBL_WRITE_ONLY));
191
192 // allocate index buffer - cone and base
193 indexData->indexCount = (3 * nVerticesInBase) + (3 * (nVerticesInBase - 2));
194 indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC, false);
195 Ogre::HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer;
196 unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(Ogre::HardwareBuffer::HBL_WRITE_ONLY));
197
198 //Positions : cone head and base
199 *pVertex++ = 0.0f;
200 *pVertex++ = 0.0f;
201 *pVertex++ = 0.0f;
202
203 *pVertex++ = 0.0f;
204 *pVertex++ = 1.0f;
205 *pVertex++ = 0.0f;
206
207 *pVertex++ = 0.0f;
208 *pVertex++ = 0.0f;
209
210 //Base :
211 float fDeltaBaseAngle = (2 * Ogre::Math::PI) / nVerticesInBase;
212 for (int i=0; i<nVerticesInBase; i++)
213 {
214 float angle = i * fDeltaBaseAngle;
215 float x0 = radius * cosf(angle);
216 float y0 = height;
217 float z0 = radius * sinf(angle);
218 *pVertex++ = x0;
219 *pVertex++ = y0;
220 *pVertex++ = z0;
221
222 Ogre::Vector3 vNormal = Ogre::Vector3(x0, y0, z0).normalisedCopy();
223 *pVertex++ = vNormal.x;
224 *pVertex++ = vNormal.y;
225 *pVertex++ = vNormal.z;
226
227 *pVertex++ = (float)i / (float)nVerticesInBase;
228 *pVertex++ = 1.0f;
229 }
230
231 //Indices :
232 //Cone head to vertices
233 for (int i=0; i<nVerticesInBase; i++)
234 {
235 *pIndices++ = 0;
236 *pIndices++ = (i%nVerticesInBase) + 1;
237 *pIndices++ = ((i+1)%nVerticesInBase) + 1;
238 }
239
240 //Cone base
241 for (int i=0; i<nVerticesInBase-2; i++)
242 {
243 *pIndices++ = 1;
244 *pIndices++ = i + 3;
245 *pIndices++ = i + 2;
246 }
247
248 // Unlock
249 vBuf->unlock();
250 iBuf->unlock();
251}
252
253Ogre::MeshPtr SBaseMeshsTools::CreateOctahedron(const Ogre::String& strName, float baseLength, float bottomDistance, float upDistance, Ogre::String groupName)
254{
255 assert(baseLength > 0);
256 assert(bottomDistance > 0);
257 assert(upDistance > 0);
258
259 Ogre::MeshPtr pOctahedron = Ogre::MeshManager::getSingleton().createManual(strName, groupName);
260 Ogre::SubMesh *pOctahedronVertex = pOctahedron->createSubMesh();
261 pOctahedron->sharedVertexData = new Ogre::VertexData();
262
263 CreateOctahedron(pOctahedron->sharedVertexData, pOctahedronVertex->indexData, baseLength, bottomDistance, upDistance);
264
265 // Generate face list
266 pOctahedronVertex->useSharedVertices = true;
267 float totalLength = bottomDistance + upDistance;
268 pOctahedron->_setBounds(Ogre::AxisAlignedBox(Ogre::Vector3(-baseLength/2, 0, -baseLength/2), Ogre::Vector3(baseLength/2, upDistance, baseLength/2)), false);
269 // TODO: verify this:
270 pOctahedron->_setBoundingSphereRadius(Ogre::Math::Sqrt(totalLength*totalLength + (baseLength/2)*(baseLength/2)));
271
272 // this line makes clear the mesh is loaded (avoids memory leaks)
273 pOctahedron->load();
274 return pOctahedron;
275}
276
277void SBaseMeshsTools::CreateOctahedron(Ogre::VertexData*& vertexData, Ogre::IndexData*& indexData, float baseLength, float bottomDistance, float upDistance)
278{
279 assert(vertexData && indexData);
280
281 // define the vertex format
282 Ogre::VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
283
284 size_t currOffset = 0;
285
286 // positions
287 vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
288 currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
289
290 // normals
291 vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
292 currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
293
294 // two dimensional texture coordinates
295 vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0);
296 currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
297
298 // allocate the vertex buffer
299 vertexData->vertexCount = 6;
300 Ogre::HardwareVertexBufferSharedPtr vBuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC, false);
301 Ogre::VertexBufferBinding* binding = vertexData->vertexBufferBinding;
302 binding->setBinding(0, vBuf);
303 float* pVertex = static_cast<float*>(vBuf->lock(Ogre::HardwareBuffer::HBL_WRITE_ONLY));
304
305 // allocate index buffer - cone and base
306 indexData->indexCount = 3 * 8;
307 indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC, false);
308 Ogre::HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer;
309 unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(Ogre::HardwareBuffer::HBL_WRITE_ONLY));
310
311 //Positions : bottom vertex
312
313 *pVertex++ = 0.0f;
314 *pVertex++ = bottomDistance;
315 *pVertex++ = 0.0f;
316
317 //Normal
318 *pVertex++ = 0.0f;
319 *pVertex++ = 1.0f;
320 *pVertex++ = 0.0f;
321
322 //UV
323 *pVertex++ = 0.0f;
324 *pVertex++ = 0.0f;
325
326 // base
327 float baseOffset = baseLength / 2.0f;
328 *pVertex++ = baseOffset; *pVertex++ = 0; *pVertex++ = baseOffset; // corner 1
329 //Normal
330 Ogre::Vector3 vNormal = Ogre::Vector3(baseOffset, 0.0f, baseOffset).normalisedCopy();
331 *pVertex++ = vNormal.x; *pVertex++ = vNormal.y; *pVertex++ = vNormal.z;
332 //UV
333 *pVertex++ = 0.0f; *pVertex++ = 0.0f;
334
335 *pVertex++ = baseOffset; *pVertex++ = 0; *pVertex++ = -baseOffset; // corner 2
336 //Normal
337 vNormal = Ogre::Vector3(baseOffset, 0.0f, -baseOffset).normalisedCopy();
338 *pVertex++ = vNormal.x; *pVertex++ = vNormal.y; *pVertex++ = vNormal.z;
339 //UV
340 *pVertex++ = 0.0f; *pVertex++ = 1.0f;
341
342 *pVertex++ = -baseOffset; *pVertex++ = 0; *pVertex++ = -baseOffset; // corner 3
343 //Normal
344 vNormal = Ogre::Vector3(-baseOffset, 0.0f, -baseOffset).normalisedCopy();
345 *pVertex++ = vNormal.x; *pVertex++ = vNormal.y; *pVertex++ = vNormal.z;
346 //UV
347 *pVertex++ = 1.0f; *pVertex++ = 1.0f;
348
349 *pVertex++ = -baseOffset; *pVertex++ = 0; *pVertex++ = baseOffset; // corner 4
350 //Normal
351 vNormal = Ogre::Vector3(-baseOffset, 0.0f, baseOffset).normalisedCopy();
352 *pVertex++ = vNormal.x; *pVertex++ = vNormal.y; *pVertex++ = vNormal.z;
353 //UV
354 *pVertex++ = 1.0f; *pVertex++ = 0.0f;
355
356 // upVertex
357 *pVertex++ = 0;
358 *pVertex++ = -upDistance;
359 *pVertex++ = 0;
360
361 //Normal
362 *pVertex++ = 0.0f;
363 *pVertex++ = -1.0f;
364 *pVertex++ = 0.0f;
365
366 //UV
367 *pVertex++ = 0.0f;
368 *pVertex++ = 1.0f;
369
370 //Indices :
371 // bottom pyramid
372 for (int i=0; i<4; i++)
373 {
374 *pIndices++ = 0;
375 *pIndices++ = (i%4) + 1;
376 *pIndices++ = ((i+1)%4) + 1;
377 }
378
379 // up pyramid
380 for (int i=0; i<4; i++)
381 {
382 *pIndices++ = ((i+1)%4) + 1;
383 *pIndices++ = (i % 4) + 1;
384 *pIndices++ = 5;
385 }
386
387 // unlock buffers
388 vBuf->unlock();
389 iBuf->unlock();
390}
391
392void SBaseMeshsTools::CreateQuad(Ogre::VertexData*& vertexData)
393{
394 assert(vertexData);
395
396 vertexData->vertexCount = 4;
397 vertexData->vertexStart = 0;
398
399 Ogre::VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
400 Ogre::VertexBufferBinding* bind = vertexData->vertexBufferBinding;
401
402 vertexDecl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
403 Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC);
404
405 // Bind buffer
406 bind->setBinding(0, vbuf);
407
408 // Upload data
409 float data[]=
410 {
411 -1,1,0, // corner 1
412 -1,-1,0, // corner 2
413 1,1,0, // corner 3
414 1,-1,0 // corner 4
415 };
416 vbuf->writeData(0, sizeof(data), data, true);
417}
418
419}
static void CreateQuad(Ogre::VertexData *&vertexData)
static Ogre::MeshPtr CreateCone(const Ogre::String &strName, float radius, float height, int nVerticesInBase, Ogre::String groupName=Ogre::RGN_DEFAULT)
static Ogre::MeshPtr CreateSphere(const Ogre::String &strName, float radius, int nRings, int nSegments, bool bNormals, bool bTexCoords, Ogre::String groupName=Ogre::RGN_DEFAULT)
static Ogre::MeshPtr CreateOctahedron(const Ogre::String &strName, float baseLength, float bottomDistance, float upDistance, Ogre::String groupName=Ogre::RGN_DEFAULT)