~ubuntu-branches/debian/sid/ember/sid

« back to all changes in this revision

Viewing changes to src/components/ogre/environment/pagedgeometry/source/GrassLoader.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Koch
  • Date: 2009-07-23 07:46:40 UTC
  • Revision ID: james.westby@ubuntu.com-20090723074640-wh0ukzis0kda36qv
Tags: upstream-0.5.6
ImportĀ upstreamĀ versionĀ 0.5.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------------------
 
2
Copyright (c) 2006 John Judnich
 
3
Modified 2008 by Erik Hjortsberg (erik.hjortsberg@gmail.com)
 
4
 
 
5
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
 
6
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
 
7
    1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
 
8
    2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
 
9
    3. This notice may not be removed or altered from any source distribution.
 
10
-------------------------------------------------------------------------------------*/
 
11
 
 
12
#include "GrassLoader.h"
 
13
#include "PagedGeometry.h"
 
14
#include "PropertyMaps.h"
 
15
 
 
16
#include <OgreRoot.h>
 
17
#include <OgreTimer.h>
 
18
#include <OgreCamera.h>
 
19
#include <OgreVector3.h>
 
20
#include <OgreQuaternion.h>
 
21
#include <OgreEntity.h>
 
22
#include <OgreString.h>
 
23
#include <OgreStringConverter.h>
 
24
#include <OgreMaterialManager.h>
 
25
#include <OgreMaterial.h>
 
26
#include <OgreHardwareBufferManager.h>
 
27
#include <OgreHardwareBuffer.h>
 
28
#include <OgreMeshManager.h>
 
29
#include <OgreMesh.h>
 
30
#include <OgreSubMesh.h>
 
31
#include <OgreLogManager.h>
 
32
#include <OgreTextureManager.h>
 
33
#include <OgreHardwarePixelBuffer.h>
 
34
#include <OgreRenderSystem.h>
 
35
#include <OgreRenderSystemCapabilities.h>
 
36
#include <OgreHighLevelGpuProgram.h>
 
37
#include <OgreHighLevelGpuProgramManager.h>
 
38
using namespace Ogre;
 
39
 
 
40
namespace PagedGeometry {
 
41
 
 
42
GrassLayer::GrassLayer(PagedGeometry *geom, GrassLoader<GrassLayer> *ldr)
 
43
{
 
44
        GrassLayer::geom = geom;
 
45
        GrassLayer::parent = ldr;
 
46
 
 
47
        density = 1.0f;
 
48
        minWidth = 1.0f; maxWidth = 1.0f;
 
49
        minHeight = 1.0f; maxHeight = 1.0f;
 
50
        minY = 0; maxY = 0;
 
51
        renderTechnique = GRASSTECH_QUAD;
 
52
        fadeTechnique = FADETECH_ALPHA;
 
53
        animMag = 1.0f;
 
54
        animSpeed = 1.0f;
 
55
        animFreq = 1.0f;
 
56
        waveCount = 0.0f;
 
57
        animate = false;
 
58
        blend = false;
 
59
        shaderNeedsUpdate = true;
 
60
 
 
61
        densityMap = NULL;
 
62
        densityMapFilter = MAPFILTER_BILINEAR;
 
63
        colorMap = NULL;
 
64
        colorMapFilter = MAPFILTER_BILINEAR;
 
65
}
 
66
 
 
67
GrassLayer::~GrassLayer()
 
68
{
 
69
        if (densityMap)
 
70
                densityMap->unload();
 
71
        if (colorMap)
 
72
                colorMap->unload();
 
73
}
 
74
 
 
75
unsigned int GrassLayer::calculateMaxGrassCount(float densityFactor, float volume)
 
76
{
 
77
        return density * densityFactor * volume;
 
78
}
 
79
 
 
80
unsigned int GrassLayer::_populateGrassList(PageInfo page, float *posBuff, unsigned int grassCount)
 
81
{
 
82
        if (densityMap){
 
83
                if (densityMap->getFilter() == MAPFILTER_NONE)
 
84
                        return _populateGrassList_UnfilteredDM(page, posBuff, grassCount);
 
85
                else if (densityMap->getFilter() == MAPFILTER_BILINEAR)
 
86
                        return _populateGrassList_BilinearDM(page, posBuff, grassCount);
 
87
        }
 
88
        return _populateGrassList_Uniform(page, posBuff, grassCount);
 
89
        
 
90
}
 
91
 
 
92
void GrassLayerBase::setMaterialName(const String &matName)
 
93
{
 
94
        if (material.isNull() || matName != material->getName()){
 
95
                material = MaterialManager::getSingleton().getByName(matName);
 
96
                if (material.isNull())
 
97
                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "The specified grass material does not exist", "GrassLayer::setMaterialName()");
 
98
                shaderNeedsUpdate = true;
 
99
        }
 
100
}
 
101
 
 
102
void GrassLayerBase::setMinimumSize(float width, float height)
 
103
{
 
104
        minWidth = width;
 
105
        minHeight = height;
 
106
}
 
107
 
 
108
void GrassLayerBase::setMaximumSize(float width, float height)
 
109
{
 
110
        maxWidth = width;
 
111
        if (maxHeight != height){
 
112
                maxHeight = height;
 
113
                shaderNeedsUpdate = true;
 
114
        }
 
115
}
 
116
 
 
117
void GrassLayerBase::setRenderTechnique(GrassTechnique style, bool blendBase)
 
118
{
 
119
        if (blend != blendBase || renderTechnique != style){
 
120
                blend = blendBase;
 
121
                renderTechnique = style;
 
122
                shaderNeedsUpdate = true;
 
123
        }
 
124
}
 
125
 
 
126
void GrassLayerBase::setFadeTechnique(FadeTechnique style)
 
127
{
 
128
        if (fadeTechnique != style){
 
129
                fadeTechnique = style;
 
130
                shaderNeedsUpdate = true;
 
131
        }
 
132
}
 
133
 
 
134
void GrassLayerBase::setAnimationEnabled(bool enabled)
 
135
{
 
136
        if (animate != enabled){
 
137
                animate = enabled;
 
138
                shaderNeedsUpdate = true;
 
139
        }
 
140
}
 
141
 
 
142
void GrassLayer::setDensityMap(const String &mapFile, MapChannel channel)
 
143
{
 
144
        if (densityMap){
 
145
                densityMap->unload();
 
146
                densityMap = NULL;
 
147
        }
 
148
        if (mapFile != ""){
 
149
                densityMap = DensityMap::load(mapFile, channel);
 
150
                densityMap->setMapBounds(mapBounds);
 
151
                densityMap->setFilter(densityMapFilter);
 
152
        }
 
153
}
 
154
void GrassLayer::setDensityMap(Texture *map, MapChannel channel)
 
155
{
 
156
        if (densityMap){
 
157
                densityMap->unload();
 
158
                densityMap = NULL;
 
159
        }
 
160
        if (map){
 
161
                densityMap = DensityMap::load(map, channel);
 
162
                densityMap->setMapBounds(mapBounds);
 
163
                densityMap->setFilter(densityMapFilter);
 
164
        }
 
165
}
 
166
 
 
167
void GrassLayer::setDensityMapFilter(MapFilter filter)
 
168
{
 
169
        densityMapFilter = filter;
 
170
        if (densityMap)
 
171
                densityMap->setFilter(densityMapFilter);
 
172
}
 
173
 
 
174
unsigned int GrassLayer::_populateGrassList_Uniform(PageInfo page, float *posBuff, unsigned int grassCount)
 
175
{
 
176
        float *posPtr = posBuff;
 
177
 
 
178
        //No density map
 
179
        if (!minY && !maxY){
 
180
                //No height range
 
181
                for (unsigned int i = 0; i < grassCount; ++i){
 
182
                        //Pick a random position
 
183
                        float x = Math::RangeRandom(page.bounds.left, page.bounds.right);
 
184
                        float z = Math::RangeRandom(page.bounds.top, page.bounds.bottom);
 
185
 
 
186
                        //Add to list in within bounds
 
187
                        if (!colorMap){
 
188
                                *posPtr++ = x;
 
189
                                *posPtr++ = z;
 
190
                        } else if (x >= mapBounds.left && x <= mapBounds.right && z >= mapBounds.top && z <= mapBounds.bottom){
 
191
                                *posPtr++ = x;
 
192
                                *posPtr++ = z;
 
193
                        }
 
194
                }
 
195
        } else {
 
196
                //Height range
 
197
                Real min, max;
 
198
                if (minY) min = minY; else min = Math::NEG_INFINITY;
 
199
                if (maxY) max = maxY; else max = Math::POS_INFINITY;
 
200
 
 
201
                for (unsigned int i = 0; i < grassCount; ++i){
 
202
                        //Pick a random position
 
203
                        float x = Math::RangeRandom(page.bounds.left, page.bounds.right);
 
204
                        float z = Math::RangeRandom(page.bounds.top, page.bounds.bottom);
 
205
 
 
206
                        //Calculate height
 
207
                        float y = parent->heightFunction(x, z, parent->heightFunctionUserData);
 
208
 
 
209
                        //Add to list if in range
 
210
                        if (y >= min && y <= max){
 
211
                                //Add to list in within bounds
 
212
                                if (!colorMap){
 
213
                                        *posPtr++ = x;
 
214
                                        *posPtr++ = z;
 
215
                                } else if (x >= mapBounds.left && x <= mapBounds.right && z >= mapBounds.top && z <= mapBounds.bottom){
 
216
                                        *posPtr++ = x;
 
217
                                        *posPtr++ = z;
 
218
                                }
 
219
                        }
 
220
                }
 
221
        }
 
222
 
 
223
        grassCount = (posPtr - posBuff) / 2;
 
224
        return grassCount;
 
225
}
 
226
 
 
227
unsigned int GrassLayer::_populateGrassList_UnfilteredDM(PageInfo page, float *posBuff, unsigned int grassCount)
 
228
{
 
229
        float *posPtr = posBuff;
 
230
 
 
231
        //Use density map
 
232
        if (!minY && !maxY){
 
233
                //No height range
 
234
                for (unsigned int i = 0; i < grassCount; ++i){
 
235
                        //Pick a random position
 
236
                        float x = Math::RangeRandom(page.bounds.left, page.bounds.right);
 
237
                        float z = Math::RangeRandom(page.bounds.top, page.bounds.bottom);
 
238
 
 
239
                        //Determine whether this grass will be added based on the local density.
 
240
                        //For example, if localDensity is .32, grasses will be added 32% of the time.
 
241
                        if (Math::UnitRandom() < densityMap->_getDensityAt_Unfiltered(x, z)){
 
242
                                //Add to list
 
243
                                *posPtr++ = x;
 
244
                                *posPtr++ = z;
 
245
                        }
 
246
                }
 
247
        } else {
 
248
                //Height range
 
249
                Real min, max;
 
250
                if (minY) min = minY; else min = Math::NEG_INFINITY;
 
251
                if (maxY) max = maxY; else max = Math::POS_INFINITY;
 
252
 
 
253
                for (unsigned int i = 0; i < grassCount; ++i){
 
254
                        //Pick a random position
 
255
                        float x = Math::RangeRandom(page.bounds.left, page.bounds.right);
 
256
                        float z = Math::RangeRandom(page.bounds.top, page.bounds.bottom);
 
257
 
 
258
                        //Determine whether this grass will be added based on the local density.
 
259
                        //For example, if localDensity is .32, grasses will be added 32% of the time.
 
260
                        if (Math::UnitRandom() < densityMap->_getDensityAt_Unfiltered(x, z)){
 
261
                                //Calculate height
 
262
                                float y = parent->heightFunction(x, z, parent->heightFunctionUserData);
 
263
 
 
264
                                //Add to list if in range
 
265
                                if (y >= min && y <= max){
 
266
                                        //Add to list
 
267
                                        *posPtr++ = x;
 
268
                                        *posPtr++ = z;
 
269
                                }
 
270
                        }
 
271
                }
 
272
        }
 
273
 
 
274
        grassCount = (posPtr - posBuff) / 2;
 
275
        return grassCount;
 
276
}
 
277
 
 
278
unsigned int GrassLayer::_populateGrassList_BilinearDM(PageInfo page, float *posBuff, unsigned int grassCount)
 
279
{
 
280
        float *posPtr = posBuff;
 
281
 
 
282
        if (!minY && !maxY){
 
283
                //No height range
 
284
                for (unsigned int i = 0; i < grassCount; ++i){
 
285
                        //Pick a random position
 
286
                        float x = Math::RangeRandom(page.bounds.left, page.bounds.right);
 
287
                        float z = Math::RangeRandom(page.bounds.top, page.bounds.bottom);
 
288
 
 
289
                        //Determine whether this grass will be added based on the local density.
 
290
                        //For example, if localDensity is .32, grasses will be added 32% of the time.
 
291
                        if (Math::UnitRandom() < densityMap->_getDensityAt_Bilinear(x, z)){
 
292
                                //Add to list
 
293
                                *posPtr++ = x;
 
294
                                *posPtr++ = z;
 
295
                        }
 
296
                }
 
297
        } else {
 
298
                //Height range
 
299
                Real min, max;
 
300
                if (minY) min = minY; else min = Math::NEG_INFINITY;
 
301
                if (maxY) max = maxY; else max = Math::POS_INFINITY;
 
302
 
 
303
                for (unsigned int i = 0; i < grassCount; ++i){
 
304
                        //Pick a random position
 
305
                        float x = Math::RangeRandom(page.bounds.left, page.bounds.right);
 
306
                        float z = Math::RangeRandom(page.bounds.top, page.bounds.bottom);
 
307
 
 
308
                        //Determine whether this grass will be added based on the local density.
 
309
                        //For example, if localDensity is .32, grasses will be added 32% of the time.
 
310
                        if (Math::UnitRandom() < densityMap->_getDensityAt_Bilinear(x, z)){
 
311
                                //Calculate height
 
312
                                float y = parent->heightFunction(x, z, parent->heightFunctionUserData);
 
313
 
 
314
                                //Add to list if in range
 
315
                                if (y >= min && y <= max){
 
316
                                        //Add to list
 
317
                                        *posPtr++ = x;
 
318
                                        *posPtr++ = z;
 
319
                                }
 
320
                        }
 
321
                }
 
322
        }
 
323
 
 
324
        grassCount = (posPtr - posBuff) / 2;
 
325
        return grassCount;
 
326
}
 
327
 
 
328
void GrassLayer::setColorMap(const String &mapFile, MapChannel channel)
 
329
{
 
330
        if (colorMap){
 
331
                colorMap->unload();
 
332
                colorMap = NULL;
 
333
        }
 
334
        if (mapFile != ""){
 
335
                colorMap = ColorMap::load(mapFile, channel);
 
336
                colorMap->setMapBounds(mapBounds);
 
337
                colorMap->setFilter(colorMapFilter);
 
338
        }
 
339
}
 
340
 
 
341
void GrassLayer::setColorMap(Texture *map, MapChannel channel)
 
342
{
 
343
        if (colorMap){
 
344
                colorMap->unload();
 
345
                colorMap = NULL;
 
346
        }
 
347
        if (map){
 
348
                colorMap = ColorMap::load(map, channel);
 
349
                colorMap->setMapBounds(mapBounds);
 
350
                colorMap->setFilter(colorMapFilter);
 
351
        }
 
352
}
 
353
 
 
354
void GrassLayer::setColorMapFilter(MapFilter filter)
 
355
{
 
356
        colorMapFilter = filter;
 
357
        if (colorMap)
 
358
                colorMap->setFilter(colorMapFilter);
 
359
}
 
360
 
 
361
void GrassLayerBase::_updateShaders()
 
362
{
 
363
        if (shaderNeedsUpdate){
 
364
                shaderNeedsUpdate = false;
 
365
 
 
366
                //Proceed only if there is no custom vertex shader and the user's computer supports vertex shaders
 
367
                const RenderSystemCapabilities *caps = Root::getSingleton().getRenderSystem()->getCapabilities();
 
368
                if (caps->hasCapability(RSC_VERTEX_PROGRAM)){
 
369
                        //Generate a string ID that identifies the current set of vertex shader options
 
370
                        StringUtil::StrStreamType tmpName;
 
371
                        tmpName << "GrassVS_";
 
372
                        if (animate)
 
373
                                tmpName << "anim_";
 
374
                        if (blend)
 
375
                                tmpName << "blend_";
 
376
                        tmpName << renderTechnique << "_";
 
377
                        tmpName << fadeTechnique << "_";
 
378
                        if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW)
 
379
                                tmpName << maxHeight << "_";
 
380
                        tmpName << "vp";
 
381
                        const String vsName = tmpName.str();
 
382
                        
 
383
                        //Generate a string ID that identifies the material combined with the vertex shader
 
384
                        const String matName = material->getName() + "_" + vsName;
 
385
 
 
386
                        //Check if the desired material already exists (if not, create it)
 
387
                        MaterialPtr tmpMat = MaterialManager::getSingleton().getByName(matName);
 
388
                        if (tmpMat.isNull()){
 
389
                                //Clone the original material
 
390
                                tmpMat = material->clone(matName);
 
391
 
 
392
                                //Disable lighting
 
393
                                tmpMat->setLightingEnabled(false);
 
394
                                //tmpMat->setReceiveShadows(false);
 
395
 
 
396
                                //Check if the desired shader already exists (if not, compile it)
 
397
                                HighLevelGpuProgramPtr vertexShader = HighLevelGpuProgramManager::getSingleton().getByName(vsName);
 
398
                                if (vertexShader.isNull()){
 
399
                                        //Generate the grass shader
 
400
                                        String vertexProgSource;
 
401
                                        vertexProgSource = 
 
402
                                                "void main( \n"
 
403
                                                "       float4 iPosition : POSITION, \n"
 
404
                                                "       float4 iColor : COLOR, \n"
 
405
                                                "       float2 iUV       : TEXCOORD0,   \n"
 
406
                                                "       out float4 oPosition : POSITION, \n"
 
407
                                                "       out float4 oColor : COLOR, \n"
 
408
                                                "       out float2 oUV       : TEXCOORD0,       \n";
 
409
 
 
410
                                        if (animate) vertexProgSource +=
 
411
                                                "       uniform float time,     \n"
 
412
                                                "       uniform float frequency,        \n"
 
413
                                                "       uniform float4 direction,       \n";
 
414
 
 
415
                                        if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW) vertexProgSource +=
 
416
                                                "       uniform float grassHeight,      \n";
 
417
 
 
418
                                        if (renderTechnique == GRASSTECH_SPRITE) vertexProgSource +=
 
419
                                                "       float4 iNormal : NORMAL, \n";
 
420
 
 
421
                                        vertexProgSource +=
 
422
                                                "       uniform float4x4 worldViewProj, \n"
 
423
                                                "       uniform float3 camPos, \n"
 
424
                                                "       uniform float fadeRange ) \n"
 
425
                                                "{      \n"
 
426
                                                "       oColor.rgb = iColor.rgb;   \n"
 
427
                                                "       float4 position = iPosition;    \n"
 
428
                                                "       float dist = distance(camPos.xz, position.xz);  \n";
 
429
 
 
430
                                        if (fadeTechnique == FADETECH_ALPHA || fadeTechnique == FADETECH_ALPHAGROW) vertexProgSource +=
 
431
                                                //Fade out in the distance
 
432
                                                "       oColor.a = 2.0f - (2.0f * dist / fadeRange);   \n";
 
433
                                        else vertexProgSource +=
 
434
                                                "       oColor.a = 1.0f;   \n";
 
435
 
 
436
                                        vertexProgSource +=
 
437
                                                "       float oldposx = position.x;     \n";
 
438
 
 
439
                                        if (renderTechnique == GRASSTECH_SPRITE) vertexProgSource +=
 
440
                                                //Face the camera
 
441
                                                "       float3 dirVec = (float3)position - (float3)camPos;              \n"
 
442
                                                "       float3 p = normalize(cross(float4(0,1,0,0), dirVec));   \n"
 
443
                                                "       position += float4(p.x * iNormal.x, iNormal.y, p.z * iNormal.x, 0);     \n";
 
444
 
 
445
                                        if (animate) vertexProgSource +=
 
446
                                                "       if (iUV.y == 0.0f){     \n"
 
447
                                                //Wave grass in breeze
 
448
                                                "               float offset = sin(time + oldposx * frequency); \n"
 
449
                                                "               position += direction * offset; \n"
 
450
                                                "       }       \n";
 
451
 
 
452
                                        if (blend && animate) vertexProgSource +=
 
453
                                                "       else {  \n";
 
454
                                        else if (blend) vertexProgSource +=
 
455
                                                "       if (iUV.y != 0.0f){     \n";
 
456
 
 
457
                                        if (blend) vertexProgSource +=
 
458
                                                //Blend the base of nearby grass into the terrain
 
459
                                                "               if (oColor.a >= 1.0f) \n"
 
460
                                                "                       oColor.a = 4.0f * ((dist / fadeRange) - 0.1f);  \n"
 
461
                                                "       }       \n";
 
462
 
 
463
                                        if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW) vertexProgSource +=
 
464
                                                "       float offset = (2.0f * dist / fadeRange) - 1.0f; \n"
 
465
                                                "       position.y -= grassHeight * clamp(offset, 0, 1); ";
 
466
 
 
467
                                        vertexProgSource +=
 
468
                                                "       oPosition = mul(worldViewProj, position);  \n";
 
469
 
 
470
                                        vertexProgSource +=
 
471
                                                "       oUV = iUV;\n"
 
472
                                                "}"; 
 
473
 
 
474
                                        vertexShader = HighLevelGpuProgramManager::getSingleton().createProgram(
 
475
                                                vsName,
 
476
                                                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
 
477
                                                "cg", GPT_VERTEX_PROGRAM);
 
478
 
 
479
                                        vertexShader->setSource(vertexProgSource);
 
480
                                        vertexShader->setParameter("profiles", "vs_1_1 arbvp1");
 
481
                                        vertexShader->setParameter("entry_point", "main");
 
482
                                        vertexShader->load();
 
483
                                }
 
484
                                //Now the vertex shader (vertexShader) has either been found or just generated
 
485
                                //(depending on whether or not it was already generated). 
 
486
 
 
487
                                //Apply the shader to the material
 
488
                                Pass *pass = tmpMat->getTechnique(0)->getPass(0);
 
489
                                pass->setVertexProgram(vsName);
 
490
                                GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters();
 
491
 
 
492
                                params->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
 
493
                                params->setNamedAutoConstant("camPos", GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE);
 
494
                                params->setNamedAutoConstant("fadeRange", GpuProgramParameters::ACT_CUSTOM, 1);
 
495
 
 
496
                                if (animate){
 
497
                                        params->setNamedAutoConstant("time", GpuProgramParameters::ACT_CUSTOM, 1);
 
498
                                        params->setNamedAutoConstant("frequency", GpuProgramParameters::ACT_CUSTOM, 1);
 
499
                                        params->setNamedAutoConstant("direction", GpuProgramParameters::ACT_CUSTOM, 4);
 
500
                                }
 
501
 
 
502
                                if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW){
 
503
                                        params->setNamedAutoConstant("grassHeight", GpuProgramParameters::ACT_CUSTOM, 1);
 
504
                                        params->setNamedConstant("grassHeight", maxHeight * 1.05f);
 
505
                                }
 
506
 
 
507
                                float farViewDist = geom->getDetailLevels().front()->getFarRange();
 
508
                                pass->getVertexProgramParameters()->setNamedConstant("fadeRange", farViewDist / 1.225f);
 
509
                                //Note: 1.225 ~= sqrt(1.5), which is necessary since the far view distance is measured from the centers
 
510
                                //of pages, while the vertex shader needs to fade grass completely out (including the closest corner)
 
511
                                //before the page center is out of range.
 
512
                        }
 
513
                        //Now the material (tmpMat) has either been found or just created (depending on whether or not it was already
 
514
                        //created). The appropriate vertex shader should be applied and the material is ready for use.
 
515
 
 
516
                        //Apply the new material
 
517
                        material = tmpMat;
 
518
                }
 
519
        }
 
520
}
 
521
 
 
522
 
 
523
unsigned long GrassPage::GUID = 0;
 
524
 
 
525
void GrassPage::init(PagedGeometry *geom)
 
526
{
 
527
        sceneMgr = geom->getSceneManager();
 
528
        rootNode = geom->getSceneNode();
 
529
}
 
530
 
 
531
GrassPage::~GrassPage()
 
532
{
 
533
        removeEntities();
 
534
}
 
535
 
 
536
void GrassPage::addEntity(Entity *entity, const Vector3 &position, const Quaternion &rotation, const Vector3 &scale, const Ogre::ColourValue &color)
 
537
{
 
538
        SceneNode *node = rootNode->createChildSceneNode();
 
539
        node->setPosition(position);
 
540
        nodeList.push_back(node);
 
541
 
 
542
        Entity *ent = entity->clone(getUniqueID());
 
543
        ent->setCastShadows(false);
 
544
        ent->setRenderQueueGroup(entity->getRenderQueueGroup());
 
545
        node->attachObject(ent);
 
546
}
 
547
 
 
548
void GrassPage::removeEntities()
 
549
{
 
550
        std::list<SceneNode*>::iterator i;
 
551
        for (i = nodeList.begin(); i != nodeList.end(); ++i){
 
552
                SceneNode *node = *i;
 
553
                sceneMgr->destroyEntity(static_cast<Entity*>(node->getAttachedObject(0)));
 
554
                sceneMgr->destroySceneNode(node->getName());
 
555
        }
 
556
        nodeList.clear();
 
557
}
 
558
 
 
559
void GrassPage::setVisible(bool visible)
 
560
{
 
561
        std::list<SceneNode*>::iterator i;
 
562
        for (i = nodeList.begin(); i != nodeList.end(); ++i){
 
563
                SceneNode *node = *i;
 
564
                node->setVisible(visible);
 
565
        }
 
566
}
 
567
}