-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathGeomUtils.cpp
171 lines (142 loc) · 5.34 KB
/
GeomUtils.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/
Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html
You may use this sample code for anything you like, it is not covered by the
LGPL like the rest of the engine.
-----------------------------------------------------------------------------
*/
#include "GeomUtils.h"
#include "OgreMeshManager.h"
#include "OgreSubMesh.h"
#include "OgreHardwareBufferManager.h"
using namespace Ogre;
void GeomUtils::createSphere( const String& strName
, const float radius
, const int nRings, const int nSegments
, bool bNormals
, bool bTexCoords)
{
MeshPtr pSphere = MeshManager::getSingleton().createManual(strName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
SubMesh *pSphereVertex = pSphere->createSubMesh();
pSphere->sharedVertexData = new VertexData();
createSphere(pSphere->sharedVertexData, pSphereVertex->indexData
, radius
, nRings, nSegments
, bNormals // need normals
, bTexCoords // need texture co-ordinates
);
// Generate face list
pSphereVertex->useSharedVertices = true;
// the original code was missing this line:
pSphere->_setBounds( AxisAlignedBox( Vector3(-radius, -radius, -radius), Vector3(radius, radius, radius) ), false );
pSphere->_setBoundingSphereRadius(radius);
// this line makes clear the mesh is loaded (avoids memory leaks)
pSphere->load();
}
void GeomUtils::createSphere(VertexData*& vertexData, IndexData*& indexData
, float radius
, int nRings, int nSegments
, bool bNormals
, bool bTexCoords)
{
assert(vertexData && indexData);
// define the vertex format
VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
size_t currOffset = 0;
// positions
vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION);
currOffset += VertexElement::getTypeSize(VET_FLOAT3);
if (bNormals)
{
// normals
vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL);
currOffset += VertexElement::getTypeSize(VET_FLOAT3);
}
// two dimensional texture coordinates
if (bTexCoords)
{
vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
currOffset += VertexElement::getTypeSize(VET_FLOAT2);
}
// allocate the vertex buffer
vertexData->vertexCount = (nRings + 1) * (nSegments+1);
HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
VertexBufferBinding* binding = vertexData->vertexBufferBinding;
binding->setBinding(0, vBuf);
float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD));
// allocate index buffer
indexData->indexCount = 6 * nRings * (nSegments + 1);
indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer;
unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD));
float fDeltaRingAngle = (Math::PI / nRings);
float fDeltaSegAngle = (2 * Math::PI / nSegments);
unsigned short wVerticeIndex = 0 ;
// Generate the group of rings for the sphere
for( int ring = 0; ring <= nRings; ring++ ) {
float r0 = radius * sinf (ring * fDeltaRingAngle);
float y0 = radius * cosf (ring * fDeltaRingAngle);
// Generate the group of segments for the current ring
for(int seg = 0; seg <= nSegments; seg++) {
float x0 = r0 * sinf(seg * fDeltaSegAngle);
float z0 = r0 * cosf(seg * fDeltaSegAngle);
// Add one vertex to the strip which makes up the sphere
*pVertex++ = x0;
*pVertex++ = y0;
*pVertex++ = z0;
if (bNormals)
{
Vector3 vNormal = Vector3(x0, y0, z0).normalisedCopy();
*pVertex++ = vNormal.x;
*pVertex++ = vNormal.y;
*pVertex++ = vNormal.z;
}
if (bTexCoords)
{
*pVertex++ = (float) seg / (float) nSegments;
*pVertex++ = (float) ring / (float) nRings;
}
if (ring != nRings)
{
// each vertex (except the last) has six indices pointing to it
*pIndices++ = wVerticeIndex + nSegments + 1;
*pIndices++ = wVerticeIndex;
*pIndices++ = wVerticeIndex + nSegments;
*pIndices++ = wVerticeIndex + nSegments + 1;
*pIndices++ = wVerticeIndex + 1;
*pIndices++ = wVerticeIndex;
wVerticeIndex ++;
}
}; // end for seg
} // end for ring
// Unlock
vBuf->unlock();
iBuf->unlock();
}
void GeomUtils::createQuad(VertexData*& vertexData)
{
assert(vertexData);
vertexData->vertexCount = 4;
vertexData->vertexStart = 0;
VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
VertexBufferBinding* bind = vertexData->vertexBufferBinding;
vertexDecl->addElement(0, 0, VET_FLOAT3, VES_POSITION);
HardwareVertexBufferSharedPtr vbuf =
HardwareBufferManager::getSingleton().createVertexBuffer(
vertexDecl->getVertexSize(0),
vertexData->vertexCount,
HardwareBuffer::HBU_STATIC_WRITE_ONLY);
// Bind buffer
bind->setBinding(0, vbuf);
// Upload data
float data[]={
-1,1,-1, // corner 1
-1,-1,-1, // corner 2
1,1,-1, // corner 3
1,-1,-1}; // corner 4
vbuf->writeData(0, sizeof(data), data, true);
}