1 | #include "Ogre.h"
|
---|
2 |
|
---|
3 |
|
---|
4 | class Grass
|
---|
5 | {
|
---|
6 | protected:
|
---|
7 | StaticGeometry* mStaticGeom;
|
---|
8 | Real mGrassHeight;
|
---|
9 | Real mGrassWidth;
|
---|
10 | String mGrassMeshName;
|
---|
11 | String mGrassMaterial;
|
---|
12 | Real mOffsetParam;
|
---|
13 | SceneManager *mSceneMgr;
|
---|
14 | Real mHeightPosition;
|
---|
15 | Real mGrassFrequency;
|
---|
16 | Real mGrassInterFrequency;
|
---|
17 | Vector3 mGrassScaleRandomRangeMin;
|
---|
18 | Vector3 mGrassScaleRandomRangeMax;
|
---|
19 | Real mGrassLandscapeSizeX;
|
---|
20 | Real mGrassLandscapeSizeZ;
|
---|
21 | bool mShadowCaster;
|
---|
22 | bool mGrassShadowReceiver;
|
---|
23 |
|
---|
24 | public:
|
---|
25 | Grass()
|
---|
26 | {
|
---|
27 | mOffsetParam = 999;
|
---|
28 | mGrassMeshName = String("grassblades");
|
---|
29 | mGrassMaterial = String("Examples/GrassBlades");
|
---|
30 | mShadowCaster = false;
|
---|
31 | }
|
---|
32 |
|
---|
33 | void setGrassCastShadows(bool shadowCaster)
|
---|
34 | {
|
---|
35 | if (shadowCaster)
|
---|
36 | {
|
---|
37 | mStaticGeom->setCastShadows(true);
|
---|
38 | mShadowCaster = true;
|
---|
39 | }
|
---|
40 | else
|
---|
41 | {
|
---|
42 | mStaticGeom->setCastShadows(false);
|
---|
43 | mShadowCaster = false;
|
---|
44 | }
|
---|
45 | }
|
---|
46 |
|
---|
47 | void setGrassLandscapeSizeX(Real landscapeSizeX)
|
---|
48 | {
|
---|
49 | mGrassLandscapeSizeX = landscapeSizeX;
|
---|
50 | }
|
---|
51 |
|
---|
52 | void setGrassLandscapeSizeZ(Real landscapeSizeZ)
|
---|
53 | {
|
---|
54 | mGrassLandscapeSizeZ = landscapeSizeZ;
|
---|
55 | }
|
---|
56 |
|
---|
57 | Real getGrassLandscapeSizeX()
|
---|
58 | {
|
---|
59 | return mGrassLandscapeSizeX;
|
---|
60 | }
|
---|
61 |
|
---|
62 | Real getGrassLandscapeSizeZ()
|
---|
63 | {
|
---|
64 | return mGrassLandscapeSizeZ;
|
---|
65 | }
|
---|
66 |
|
---|
67 | void setGrassScaleRandomRangeMin(Vector3 scaleRRmin)
|
---|
68 | {
|
---|
69 | mGrassScaleRandomRangeMin = scaleRRmin;
|
---|
70 | }
|
---|
71 |
|
---|
72 | Vector3 getGrassScaleRandomRangeMin()
|
---|
73 | {
|
---|
74 | return mGrassScaleRandomRangeMin;
|
---|
75 | }
|
---|
76 |
|
---|
77 | void setGrassScaleRandomRangeMax(Vector3 scaleRRmax)
|
---|
78 | {
|
---|
79 | mGrassScaleRandomRangeMax = scaleRRmax;
|
---|
80 | }
|
---|
81 |
|
---|
82 | Vector3 getGrassScaleRandomRangeMax()
|
---|
83 | {
|
---|
84 | return mGrassScaleRandomRangeMax;
|
---|
85 | }
|
---|
86 |
|
---|
87 | void setGrassInterFrequency(Real interFrequency)
|
---|
88 | {
|
---|
89 | mGrassInterFrequency = interFrequency;
|
---|
90 | }
|
---|
91 |
|
---|
92 | Real getGrassInterFrequency()
|
---|
93 | {
|
---|
94 | return mGrassInterFrequency;
|
---|
95 | }
|
---|
96 |
|
---|
97 | void setGrassFrequency(Real frequency)
|
---|
98 | {
|
---|
99 | mGrassFrequency = frequency;
|
---|
100 | }
|
---|
101 |
|
---|
102 | Real getGrassFrequency()
|
---|
103 | {
|
---|
104 | return mGrassFrequency;
|
---|
105 | }
|
---|
106 |
|
---|
107 | void setGrassHeightPosition(Real heightPosition)
|
---|
108 | {
|
---|
109 | mHeightPosition = heightPosition;
|
---|
110 | }
|
---|
111 |
|
---|
112 | Real getGrassHeightPosition()
|
---|
113 | {
|
---|
114 | return mHeightPosition;
|
---|
115 | }
|
---|
116 |
|
---|
117 | void setSceneManager(SceneManager* sceneMgr)
|
---|
118 | {
|
---|
119 | mSceneMgr = sceneMgr;
|
---|
120 | }
|
---|
121 |
|
---|
122 | Real getGrassHeight()
|
---|
123 | {
|
---|
124 | return mGrassHeight;
|
---|
125 | }
|
---|
126 |
|
---|
127 | Real getGrassWidth()
|
---|
128 | {
|
---|
129 | return mGrassWidth;
|
---|
130 | }
|
---|
131 |
|
---|
132 | String getGrassMeshName()
|
---|
133 | {
|
---|
134 | return mGrassMeshName;
|
---|
135 | }
|
---|
136 |
|
---|
137 | String getGrassMaterial()
|
---|
138 | {
|
---|
139 | return mGrassMaterial;
|
---|
140 | }
|
---|
141 |
|
---|
142 | StaticGeometry* getStaticGeometry()
|
---|
143 | {
|
---|
144 | return mStaticGeom;
|
---|
145 | }
|
---|
146 |
|
---|
147 | void setGrassHeight(Real height)
|
---|
148 | {
|
---|
149 | mGrassHeight = height;
|
---|
150 | }
|
---|
151 |
|
---|
152 | void setGrassWidth(Real width)
|
---|
153 | {
|
---|
154 | mGrassWidth = width;
|
---|
155 | }
|
---|
156 |
|
---|
157 | void setGrassMeshName(String meshName)
|
---|
158 | {
|
---|
159 | mGrassMeshName = meshName;
|
---|
160 | }
|
---|
161 |
|
---|
162 | void setGrassMaterial(String material)
|
---|
163 | {
|
---|
164 | mGrassMaterial = material;
|
---|
165 | }
|
---|
166 |
|
---|
167 | void waveGrass(Real timeElapsed)
|
---|
168 | {
|
---|
169 | static Real xinc = Math::PI * 0.4;
|
---|
170 | static Real zinc = Math::PI * 0.55;
|
---|
171 | static Real xpos = Math::RangeRandom(-Math::PI, Math::PI);
|
---|
172 | static Real zpos = Math::RangeRandom(-Math::PI, Math::PI);
|
---|
173 |
|
---|
174 | xpos += xinc * timeElapsed;
|
---|
175 | zpos += zinc * timeElapsed;
|
---|
176 |
|
---|
177 | // Update vertex program parameters by binding a value to each renderable
|
---|
178 | static Vector4 offset(0,0,0,0);
|
---|
179 |
|
---|
180 | StaticGeometry::RegionIterator rit = mStaticGeom->getRegionIterator();
|
---|
181 | while (rit.hasMoreElements())
|
---|
182 | {
|
---|
183 | StaticGeometry::Region* reg = rit.getNext();
|
---|
184 |
|
---|
185 | // a little randomness
|
---|
186 | xpos += reg->getCentre().x * 0.001;
|
---|
187 | zpos += reg->getCentre().z * 0.001;
|
---|
188 | offset.x = Math::Sin(xpos) * 0.05;
|
---|
189 | offset.z = Math::Sin(zpos) * 0.05;
|
---|
190 |
|
---|
191 | StaticGeometry::Region::LODIterator lodit = reg->getLODIterator();
|
---|
192 | while (lodit.hasMoreElements())
|
---|
193 | {
|
---|
194 | StaticGeometry::LODBucket* lod = lodit.getNext();
|
---|
195 | StaticGeometry::LODBucket::MaterialIterator matit =
|
---|
196 | lod->getMaterialIterator();
|
---|
197 | while (matit.hasMoreElements())
|
---|
198 | {
|
---|
199 | StaticGeometry::MaterialBucket* mat = matit.getNext();
|
---|
200 | StaticGeometry::MaterialBucket::GeometryIterator geomit =
|
---|
201 | mat->getGeometryIterator();
|
---|
202 | while (geomit.hasMoreElements())
|
---|
203 | {
|
---|
204 | StaticGeometry::GeometryBucket* geom = geomit.getNext();
|
---|
205 | geom->setCustomParameter(mOffsetParam, offset);
|
---|
206 |
|
---|
207 | }
|
---|
208 | }
|
---|
209 | }
|
---|
210 | }
|
---|
211 | }
|
---|
212 |
|
---|
213 | void createGrassMesh()
|
---|
214 | {
|
---|
215 | // Each grass section is 3 planes at 60 degrees to each other
|
---|
216 | // Normals point straight up to simulate correct lighting
|
---|
217 | MeshPtr msh = MeshManager::getSingleton().createManual(mGrassMeshName,
|
---|
218 | ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
---|
219 | SubMesh* sm = msh->createSubMesh();
|
---|
220 | sm->useSharedVertices = false;
|
---|
221 | sm->vertexData = new VertexData();
|
---|
222 | sm->vertexData->vertexStart = 0;
|
---|
223 | sm->vertexData->vertexCount = 12;
|
---|
224 | VertexDeclaration* dcl = sm->vertexData->vertexDeclaration;
|
---|
225 | size_t offset = 0;
|
---|
226 | dcl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
|
---|
227 | offset += VertexElement::getTypeSize(VET_FLOAT3);
|
---|
228 | dcl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
|
---|
229 | offset += VertexElement::getTypeSize(VET_FLOAT3);
|
---|
230 | dcl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES);
|
---|
231 | offset += VertexElement::getTypeSize(VET_FLOAT2);
|
---|
232 |
|
---|
233 | HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton()
|
---|
234 | .createVertexBuffer(
|
---|
235 | offset, 12, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
|
---|
236 | float* pReal = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
|
---|
237 | Vector3 baseVec(mGrassWidth/2, 0, 0);
|
---|
238 | Vector3 vec = baseVec;
|
---|
239 | Quaternion rot;
|
---|
240 | rot.FromAngleAxis(Degree(60), Vector3::UNIT_Y);
|
---|
241 | int i;
|
---|
242 | for (i = 0; i < 3; ++i)
|
---|
243 | {
|
---|
244 | // position
|
---|
245 | *pReal++ = -vec.x;
|
---|
246 | *pReal++ = mGrassHeight;
|
---|
247 | *pReal++ = -vec.z;
|
---|
248 | // normal
|
---|
249 | *pReal++ = 0;
|
---|
250 | *pReal++ = 1;
|
---|
251 | *pReal++ = 0;
|
---|
252 | // uv
|
---|
253 | *pReal++ = 0;
|
---|
254 | *pReal++ = 0;
|
---|
255 |
|
---|
256 | // position
|
---|
257 | *pReal++ = vec.x;
|
---|
258 | *pReal++ = mGrassHeight;
|
---|
259 | *pReal++ = vec.z;
|
---|
260 | // normal
|
---|
261 | *pReal++ = 0;
|
---|
262 | *pReal++ = 1;
|
---|
263 | *pReal++ = 0;
|
---|
264 | // uv
|
---|
265 | *pReal++ = 1;
|
---|
266 | *pReal++ = 0;
|
---|
267 |
|
---|
268 | // position
|
---|
269 | *pReal++ = -vec.x;
|
---|
270 | *pReal++ = 0;
|
---|
271 | *pReal++ = -vec.z;
|
---|
272 | // normal
|
---|
273 | *pReal++ = 0;
|
---|
274 | *pReal++ = 1;
|
---|
275 | *pReal++ = 0;
|
---|
276 | // uv
|
---|
277 | *pReal++ = 0;
|
---|
278 | *pReal++ = 1;
|
---|
279 |
|
---|
280 | // position
|
---|
281 | *pReal++ = vec.x;
|
---|
282 | *pReal++ = 0;
|
---|
283 | *pReal++ = vec.z;
|
---|
284 | // normal
|
---|
285 | *pReal++ = 0;
|
---|
286 | *pReal++ = 1;
|
---|
287 | *pReal++ = 0;
|
---|
288 | // uv
|
---|
289 | *pReal++ = 1;
|
---|
290 | *pReal++ = 1;
|
---|
291 |
|
---|
292 | vec = rot * vec;
|
---|
293 | }
|
---|
294 | vbuf->unlock();
|
---|
295 | sm->vertexData->vertexBufferBinding->setBinding(0, vbuf);
|
---|
296 | sm->indexData->indexCount = 6*3;
|
---|
297 | sm->indexData->indexBuffer = HardwareBufferManager::getSingleton()
|
---|
298 | .createIndexBuffer(HardwareIndexBuffer::IT_16BIT, 6*3,
|
---|
299 | HardwareBuffer::HBU_STATIC_WRITE_ONLY);
|
---|
300 | uint16* pI = static_cast<uint16*>(
|
---|
301 | sm->indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD));
|
---|
302 | for (i = 0; i < 3; ++i)
|
---|
303 | {
|
---|
304 | int off = i*4;
|
---|
305 | *pI++ = 0 + off;
|
---|
306 | *pI++ = 3 + off;
|
---|
307 | *pI++ = 1 + off;
|
---|
308 |
|
---|
309 | *pI++ = 0 + off;
|
---|
310 | *pI++ = 2 + off;
|
---|
311 | *pI++ = 3 + off;
|
---|
312 | }
|
---|
313 |
|
---|
314 | sm->indexData->indexBuffer->unlock();
|
---|
315 | sm->setMaterialName(mGrassMaterial);
|
---|
316 | MaterialPtr material = MaterialManager::getSingleton().getByName(mGrassMaterial);
|
---|
317 | material->setReceiveShadows(mGrassShadowReceiver);
|
---|
318 | msh->load();
|
---|
319 |
|
---|
320 | }
|
---|
321 |
|
---|
322 | // This method should be called in the createScene method...
|
---|
323 | void initGrass()
|
---|
324 | {
|
---|
325 | createGrassMesh();
|
---|
326 |
|
---|
327 | Entity* e = mSceneMgr->createEntity("1", mGrassMeshName);
|
---|
328 |
|
---|
329 | StaticGeometry* s = mSceneMgr->createStaticGeometry("bing");
|
---|
330 | s->setRegionDimensions(Vector3(1000,1000,1000));
|
---|
331 | // Set the region origin so the centre is at 0 world
|
---|
332 | s->setOrigin(Vector3(-500, 500, -500));
|
---|
333 |
|
---|
334 | for (int x = -mGrassLandscapeSizeX; x < mGrassLandscapeSizeX; x += mGrassFrequency)
|
---|
335 | {
|
---|
336 | for (int z = -mGrassLandscapeSizeZ; z < mGrassLandscapeSizeZ; z += mGrassFrequency)
|
---|
337 | {
|
---|
338 | Vector3 pos(
|
---|
339 | x + Math::RangeRandom(-mGrassInterFrequency,mGrassInterFrequency),
|
---|
340 | mHeightPosition,
|
---|
341 | z + Math::RangeRandom(-mGrassInterFrequency,mGrassInterFrequency));
|
---|
342 | Quaternion orientation;
|
---|
343 | orientation.FromAngleAxis(
|
---|
344 | Degree(Math::RangeRandom(0, 359)),
|
---|
345 | Vector3::UNIT_Y);
|
---|
346 | Vector3 grassScale = Vector3(Math::RangeRandom(mGrassScaleRandomRangeMin[0],mGrassScaleRandomRangeMax[0]),
|
---|
347 | Math::RangeRandom(mGrassScaleRandomRangeMin[1],mGrassScaleRandomRangeMax[1]),
|
---|
348 | Math::RangeRandom(mGrassScaleRandomRangeMin[2],mGrassScaleRandomRangeMax[2]));
|
---|
349 | Vector3 scale(grassScale);
|
---|
350 | s->addEntity(e, pos, orientation, scale);
|
---|
351 | }
|
---|
352 |
|
---|
353 | }
|
---|
354 |
|
---|
355 | s->build();
|
---|
356 | mStaticGeom = s;
|
---|
357 |
|
---|
358 | setGrassCastShadows(mShadowCaster);
|
---|
359 | }
|
---|
360 |
|
---|
361 | void setGrassShadowReceiver(bool value)
|
---|
362 | {
|
---|
363 | mGrassShadowReceiver = value;
|
---|
364 | }
|
---|
365 | }; |
---|