Rigs of Rods 2023.09
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
MeshManager.cpp
Go to the documentation of this file.
1/*
2--------------------------------------------------------------------------------
3This source file is part of SkyX.
4Visit http://www.paradise-studios.net/products/skyx/
5
6Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez <xavyiy@gmail.com>
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#include "MeshManager.h"
25
26#include "SkyX.h"
27
28namespace SkyX
29{
31 : mSkyX(s)
32 , mCreated(false)
33 , mMesh(static_cast<Ogre::Mesh*>(0))
34 , mSubMesh(0)
35 , mEntity(0)
36 , mVertexBuffer()
37 , mVertices(0)
38 , mIndexBuffer()
39 , mSceneNode(0)
40 , mSteps(70)
41 , mCircles(95)
42 , mUnderHorizonCircles(12)
43 , mUnderHorizonFading(true)
44 , mUnderHorizonFadingExponent(0.75)
45 , mUnderHorizonFadingMultiplier(2)
46 , mRadiusMultiplier(0.95f)
47 , mMaterialName("_NULL_")
48 {
49 }
50
55
57 {
58 if (!mCreated)
59 {
60 return;
61 }
62
63 mSceneNode->detachAllObjects();
64 mSceneNode->getParentSceneNode()->removeAndDestroyChild(mSceneNode);
65 mSceneNode = 0;
66
67 Ogre::MeshManager::getSingleton().remove("SkyXMesh");
68 mSkyX->getSceneManager()->destroyEntity(mEntity);
69
70 mMesh.reset();
71 mSubMesh = 0;
72 mEntity = 0;
73 mVertexBuffer.reset();
74 mIndexBuffer.reset();
75 mMaterialName = "_NULL_";
76
77 delete [] mVertices;
78
79 mCreated = false;
80 }
81
83 {
84 if (mCreated)
85 {
86 return;
87 }
88
89 // Create mesh and submesh
90 mMesh = Ogre::MeshManager::getSingleton().createManual("SkyXMesh",
91 Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
92 mSubMesh = mMesh->createSubMesh();
93 mSubMesh->useSharedVertices = false;
94
95 // Create mesh geometry
97
98 // Build edge list
99 mMesh->buildEdgeList();
100
101 // End mesh creation
102 mMesh->load();
103 mMesh->touch();
104
105 mEntity = mSkyX->getSceneManager()->createEntity("SkyXMeshEnt", "SkyXMesh");
106 mEntity->setMaterialName(mMaterialName);
107 mEntity->setCastShadows(false);
108 mEntity->setRenderQueueGroup(mSkyX->getRenderQueueGroups().skydome);
109
110 mSceneNode = mSkyX->getSceneManager()->getRootSceneNode()->createChildSceneNode();
111 mSceneNode->showBoundingBox(false);
112 mSceneNode->attachObject(mEntity);
113
114 mCreated = true;
115 }
116
117 void MeshManager::updateGeometry(Ogre::Camera* cam)
118 {
119 if (!mCreated)
120 {
121 return;
122 }
123
124 float Radius = getSkydomeRadius(cam);
125
126 mVertices[0].x = 0; mVertices[0].z = 0; mVertices[0].y = Radius;
127 mVertices[0].nx = 0; mVertices[0].nz = 0; mVertices[0].ny = 1;
128 mVertices[0].u = 4; mVertices[0].v = 4;
129 mVertices[0].o = 1;
130
131 float AngleStep = (Ogre::Math::PI/2) / (mCircles-mUnderHorizonCircles);
132
133 float r, uvr, c, s, h;
134 float currentPhiAngle, currentTethaAngle;
135 int x, y;
136
137 // Above-horizon
139 {
140 currentTethaAngle = Ogre::Math::PI/2 - AngleStep*(y+1);
141
142 r = Ogre::Math::Cos(currentTethaAngle);
143 h = Ogre::Math::Sin(currentTethaAngle);
144
145 uvr = static_cast<float>(y+1)/(mCircles-mUnderHorizonCircles);
146
147 for(x=0;x<mSteps;x++)
148 {
149 currentPhiAngle = Ogre::Math::TWO_PI * x / mSteps;
150
151 c = Ogre::Math::Cos(currentPhiAngle) * r;
152 s = Ogre::Math::Sin(currentPhiAngle) * r;
153
154 mVertices[1+y*mSteps + x].x = c * Radius;
155 mVertices[1+y*mSteps + x].z = s * Radius;
156 mVertices[1+y*mSteps + x].y = h * Radius;
157
158 mVertices[1+y*mSteps + x].nx = c;
159 mVertices[1+y*mSteps + x].nz = s;
160 mVertices[1+y*mSteps + x].ny = h;
161
162 mVertices[1+y*mSteps + x].u = (1 + c*uvr/r)*4;
163 mVertices[1+y*mSteps + x].v = (1 + s*uvr/r)*4;
164
165 mVertices[1+y*mSteps + x].o = 1;
166 }
167 }
168
169 float op; // Opacity
170
171 // Under-horizon
173 {
174 currentTethaAngle = Ogre::Math::PI/2 - AngleStep*(y+1);
175
176 r = Ogre::Math::Cos(currentTethaAngle);
177 h = Ogre::Math::Sin(currentTethaAngle);
178
179 uvr = static_cast<float>(y+1)/(mCircles-mUnderHorizonCircles);
180
181 op = Ogre::Math::Clamp<Ogre::Real>(Ogre::Math::Pow(static_cast<Ogre::Real>(mCircles-y-1) / mUnderHorizonCircles, mUnderHorizonFadingExponent)*mUnderHorizonFadingMultiplier, 0, 1);
182
183 for(x=0;x<mSteps;x++)
184 {
185 currentPhiAngle = Ogre::Math::TWO_PI * x / mSteps;
186
187 c = Ogre::Math::Cos(currentPhiAngle) * r;
188 s = Ogre::Math::Sin(currentPhiAngle) * r;
189
190 mVertices[1+y*mSteps + x].x = c * Radius;
191 mVertices[1+y*mSteps + x].z = s * Radius;
192 mVertices[1+y*mSteps + x].y = h * Radius;
193
194 mVertices[1+y*mSteps + x].nx = c;
195 mVertices[1+y*mSteps + x].nz = s;
196 mVertices[1+y*mSteps + x].ny = h;
197
198 mVertices[1+y*mSteps + x].u = (1 + c*uvr/r)*4;
199 mVertices[1+y*mSteps + x].v = (1 + s*uvr/r)*4;
200
201 mVertices[1+y*mSteps + x].o = op;
202 }
203 }
204
205 // Update data
207 writeData(0,
208 mVertexBuffer->getSizeInBytes(),
209 mVertices,
210 true);
211
212 // Update bounds
213 Ogre::AxisAlignedBox meshBounds =
214 Ogre::AxisAlignedBox(-Radius, 0, -Radius,
215 Radius, Radius, Radius);
216
217 mMesh->_setBounds(meshBounds);
218 mSceneNode->_updateBounds();
219 }
220
222 {
223 int numVertices = mSteps * mCircles + 1;
224 int numEle = 6 * mSteps * (mCircles-1) + 3 * mSteps;
225
226 // Vertex buffers
227 mSubMesh->vertexData = new Ogre::VertexData();
228 mSubMesh->vertexData->vertexStart = 0;
229 mSubMesh->vertexData->vertexCount = numVertices;
230
231 Ogre::VertexDeclaration* vdecl = mSubMesh->vertexData->vertexDeclaration;
232 Ogre::VertexBufferBinding* vbind = mSubMesh->vertexData->vertexBufferBinding;
233
234 size_t offset = 0;
235 vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
236 offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
237 vdecl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_TEXTURE_COORDINATES, 0);
238 offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
239 vdecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 1);
240 offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
241 vdecl->addElement(0, offset, Ogre::VET_FLOAT1, Ogre::VES_TEXTURE_COORDINATES, 2);
242
243 mVertexBuffer = Ogre::HardwareBufferManager::getSingleton().
244 createVertexBuffer(sizeof(VERTEX),
245 numVertices,
246 Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
247
248 vbind->setBinding(0, mVertexBuffer);
249
250 unsigned short *indexbuffer = new unsigned short[numEle];
251
252 for (int k = 0; k < mSteps; k++)
253 {
254 indexbuffer[k*3] = 0;
255 indexbuffer[k*3+1] = k+1;
256
257 if (k != mSteps-1)
258 {
259 indexbuffer[k*3+2] = k+2;
260 }
261 else
262 {
263 indexbuffer[k*3+2] = 1;
264 }
265 }
266
267 unsigned short *twoface;
268
269 for(int y=0; y<mCircles-1; y++)
270 {
271 for(int x=0; x<mSteps; x++)
272 {
273 twoface = indexbuffer + (y*mSteps+x)*6 + 3 * mSteps;
274
275 int p0 = 1+y * mSteps + x ;
276 int p1 = 1+y * mSteps + x + 1 ;
277 int p2 = 1+(y+1)* mSteps + x ;
278 int p3 = 1+(y+1)* mSteps + x + 1 ;
279
280 if (x == mSteps-1)
281 {
282 p1 -= x+1;
283 p3 -= x+1;
284 }
285
286 // First triangle
287 twoface[2]=p0;
288 twoface[1]=p1;
289 twoface[0]=p2;
290
291 // Second triangle
292 twoface[5]=p1;
293 twoface[4]=p3;
294 twoface[3]=p2;
295 }
296 }
297
298 // Prepare buffer for indices
300 Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
301 Ogre::HardwareIndexBuffer::IT_16BIT,
302 numEle,
303 Ogre::HardwareBuffer::HBU_STATIC, true);
304
306 writeData(0,
307 mIndexBuffer->getSizeInBytes(),
308 indexbuffer,
309 true);
310
311 delete []indexbuffer;
312
313 // Set index buffer for this submesh
314 mSubMesh->indexData->indexBuffer = mIndexBuffer;
315 mSubMesh->indexData->indexStart = 0;
316 mSubMesh->indexData->indexCount = numEle;
317
318 // Create our internal buffer for manipulations
319 mVertices = new VERTEX[1+mSteps * mCircles];
320 }
321
322 void MeshManager::setGeometryParameters(const int &Steps, const int &Circles)
323 {
324 mSteps = Steps;
325 mCircles = Circles;
326
327 if (mCreated)
328 {
329 remove();
330 create();
331 }
332 }
333
334 void MeshManager::setUnderHorizonParams(const int& UnderHorizonCircles, const bool& UnderHorizonFading, const Ogre::Real& UnderHorizonFadingExponent, const Ogre::Real& UnderHorizonFadingMultiplier)
335 {
336 bool needToRecreate = (mUnderHorizonCircles != UnderHorizonCircles);
337
338 mUnderHorizonCircles = UnderHorizonCircles;
339 mUnderHorizonFading = UnderHorizonFading;
340 mUnderHorizonFadingExponent = UnderHorizonFadingExponent;
341 mUnderHorizonFadingMultiplier = UnderHorizonFadingMultiplier;
342
343 if (needToRecreate)
344 {
345 remove();
346 create();
347 }
348 }
349
350 void MeshManager::setMaterialName(const Ogre::String& MaterialName)
351 {
352 mMaterialName = MaterialName;
353
354 if (mCreated)
355 {
356 mEntity->setMaterialName(MaterialName);
357 }
358 }
359
360 const float MeshManager::getSkydomeRadius(Ogre::Camera* c) const
361 {
362 float cameraFarClipDistance = c->getFarClipDistance();
363
364 if (!cameraFarClipDistance)
365 {
366 cameraFarClipDistance = mSkyX->getInfiniteCameraFarClipDistance();
367 }
368
369 return cameraFarClipDistance*mRadiusMultiplier;
370 }
371}
void setMaterialName(const Ogre::String &MaterialName)
Set mesh material.
int mCircles
Circles.
Ogre::HardwareIndexBufferSharedPtr mIndexBuffer
Index buffer.
Ogre::String mMaterialName
Material name.
void _createGeometry()
Create geometry.
Ogre::Real mUnderHorizonFadingMultiplier
Under-horizon fading multiplier: opacity = saturate(pow(opacity,fading_exp)*fading_multiplier)
MeshManager(SkyX *s)
Constructor.
void create()
Create our water mesh, geometry, entity, etc...
void remove()
Remove all resources.
bool mUnderHorizonFading
Under-horizon fading.
Ogre::Real mRadiusMultiplier
Radius multiplier.
void updateGeometry(Ogre::Camera *cam)
Update geometry.
void setGeometryParameters(const int &Steps, const int &Circles)
Set geometry parameters.
SkyX * mSkyX
Main SkyX pointer.
Ogre::SceneNode * mSceneNode
Ogre::SceneNode pointer.
bool mCreated
Has been create() already called?
void setUnderHorizonParams(const int &UnderHorizonCircles=15, const bool &UnderHorizonFading=true, const Ogre::Real &UnderHorizonFadingExponent=1, const Ogre::Real &UnderHorizonFadingMultiplier=2)
Set under-horizon rendering params.
~MeshManager()
Destructor.
int mUnderHorizonCircles
Under-horizon rendering.
Ogre::SubMesh * mSubMesh
Ogre::Submesh pointer.
const float getSkydomeRadius(Ogre::Camera *c) const
Get skydome radius.
Ogre::MeshPtr mMesh
Ogre::MeshPtr.
Ogre::Real mUnderHorizonFadingExponent
Under-horizon exponent fading (1=linear fading)
Ogre::HardwareVertexBufferSharedPtr mVertexBuffer
Vertex buffer.
VERTEX * mVertices
Vertices.
Ogre::Entity * mEntity
Ogre::Entity pointer.
const Ogre::Real & getInfiniteCameraFarClipDistance() const
Get infinite cmaera far clip distance.
Definition SkyX.h:307
Ogre::SceneManager * getSceneManager()
Get scene manager.
Definition SkyX.h:315
const RenderQueueGroups & getRenderQueueGroups() const
Get render queue groups.
Definition SkyX.h:257
Ogre::uint8 skydome
Skydome render queue group (Note: Moon = skydome_render_queue+1)
Definition SkyX.h:80