1
/***************************************************************************
2
OgrePagingLandScapeTexture.cpp - description
4
begin : Fri Apr 16 2004
5
copyright : (C) 2003-2006 by Jose A Milan && Tuan Kuranes
6
email : spoke@supercable.es & tuan.kuranes@free.fr
7
***************************************************************************/
9
/***************************************************************************
11
* This program is free software; you can redistribute it and/or modify *
12
* it under the terms of the GNU Lesser General Public License as published by *
13
* the Free Software Foundation; either version 2 of the License, or *
14
* (at your option) any later version. *
16
***************************************************************************/
18
#include "OgrePagingLandScapePrecompiledHeaders.h"
20
#include "OgreVector3.h"
21
#include "OgreColourValue.h"
23
#include "OgreStringConverter.h"
24
#include "OgreMaterialManager.h"
25
#include "OgreTextureManager.h"
26
#include "OgreTechnique.h"
29
#include "OgrePagingLandScapeTexture.h"
31
#include "OgrePagingLandScapeOptions.h"
32
#include "OgrePagingLandScapeSceneManager.h"
33
#include "OgrePagingLandScapeTextureManager.h"
34
#include "OgrePagingLandScapeData2DManager.h"
35
#include "OgrePagingLandScapeData2D.h"
37
#include "fileutils.h"
41
//-----------------------------------------------------------------------
42
PagingLandScapeTexture::PagingLandScapeTexture(PagingLandScapeTextureManager *textureMgr,
43
const String materialBaseName,
44
const unsigned int numTexture,
45
const bool isSplatMode) :
47
mMaterialBaseName(materialBaseName),
52
mPaintRect (0, 0, 0, 0, 0, 1),
53
mIsPaintRectModified(false),
54
mDeformRect (0, 0, 0, 0, 0, 1),
55
mIsDeformRectModified(false),
56
mIsSplatMode(isSplatMode),
57
mNumTexture(numTexture),
59
mIsShaderShadowed(false),
64
//-----------------------------------------------------------------------
65
PagingLandScapeTexture::~PagingLandScapeTexture()
67
mNumChannelperTexture.clear();
71
doTextureNeedUpdate.clear();
72
isTextureModified.clear();
74
//-----------------------------------------------------------------------
75
void PagingLandScapeTexture::setNumTexture()
79
mNumChannelperTexture.reserve(mNumTexture);
80
doTextureNeedUpdate.reserve(mNumTexture);
81
isTextureModified.reserve(mNumTexture);
82
mTextures.reserve(mNumTexture);
83
mBuffers.reserve(mNumTexture);
85
mImages.reserve(mNumTexture);
87
mNumChannelperTexture.resize(mNumTexture);
88
doTextureNeedUpdate.resize(mNumTexture);
89
isTextureModified.resize(mNumTexture);
90
mTextures.resize(mNumTexture);
91
mBuffers.resize(mNumTexture);
93
mImages.resize(mNumTexture);
95
for (size_t i = 0; i < mNumTexture; i++)
97
mImages[i].loadDynamicImage (0, 0, 0, 1, PF_R8G8B8A8, true, 1, 0);
102
//-----------------------------------------------------------------------
103
const String &PagingLandScapeTexture::getMaterialName()
105
return mMaterial->getName ();
107
//-----------------------------------------------------------------------
108
void PagingLandScapeTexture::bindCompressionSettings()
110
const PagingLandScapeOptions * const opt = mParent->getOptions();
112
Material::TechniqueIterator tIt = mMaterial->getTechniqueIterator ();
113
while (tIt.hasMoreElements ())
115
Technique * const t = tIt.getNext ();
116
Technique::PassIterator pIt = t->getPassIterator ();
117
while (pIt.hasMoreElements ())
119
Pass *p = pIt.getNext ();
120
if (p->hasVertexProgram ())
122
// vertex compression setting
123
GpuProgramParametersSharedPtr params = p->getVertexProgramParameters();
124
if (opt->VertexCompression)
126
bindCompressionSettings (params);
127
bindCompressionSettings (p->getShadowReceiverVertexProgramParameters ());
132
GpuConstantDefinition const * const e = params->_findNamedConstantDefinition("splatSettings", false);
135
// use index to get RealConstantEntry
136
params->_writeRawConstant(e->physicalIndex + 0, opt->matHeight[1]);
137
params->_writeRawConstant(e->physicalIndex + 1, opt->matHeight[2]);
138
params->_writeRawConstant(e->physicalIndex + 2, float(opt->maxValue));
139
params->_writeRawConstant(e->physicalIndex + 3, 0.0f);
142
GpuProgramParameters::RealConstantEntry * const e = params->getNamedRealConstantEntry ("splatSettings");
145
e->val[0] = static_cast <float> (opt->matHeight[1]);
146
e->val[1] = static_cast <float> (opt->matHeight[2]);
147
e->val[2] = static_cast <float> (opt->maxValue);
148
e->val[3] = static_cast <float> (0.0);
158
//-----------------------------------------------------------------------
159
void PagingLandScapeTexture::bindCompressionSettings(GpuProgramParametersSharedPtr params)
161
GpuProgramParameters::AutoConstantIterator aci = params->getAutoConstantIterator();
163
while (aci.hasMoreElements())
165
const GpuProgramParameters::AutoConstantEntry& ace = aci.getNext();
166
if (ace.paramType == GpuProgramParameters::ACT_CUSTOM &&
167
ace.data == MORPH_CUSTOM_PARAM_ID)
174
params->setNamedAutoConstant("compressionSettings",
175
GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID);
178
//-----------------------------------------------------------------------
179
void PagingLandScapeTexture::loadTexturesToModify()
181
if (mNumTexture > 0 || (mIsShadowed && !mIsShaderShadowed))
183
const String nameSep(".");
184
const PagingLandScapeOptions * const opt = mParent->getOptions();
185
const String filename (opt->LandScape_filename);
186
const String commonName (StringConverter::toString(mDataZ) +
187
nameSep + StringConverter::toString(mDataX));
189
unsigned int channel = 0;
190
TextureManager* texMgr = TextureManager::getSingletonPtr();
192
const unsigned short numLodLevels =
193
mMaterial->getNumLodLevels(MaterialManager::getSingleton()._getActiveSchemeIndex());
194
// some texture are shared between techniques, ensure it's loaded once.
195
bool imageLoaded = false;
196
bool baseLoaded = false;
197
bool coverageLoaded = false;
198
bool lightLoaded = false;
199
bool horizonLoaded = false;
201
for(unsigned short k = 0; k < numLodLevels; k++)
203
Technique *t = mMaterial->getBestTechnique (k);
204
Technique::PassIterator pIt = t->getPassIterator ();
207
while (pIt.hasMoreElements ())
209
Pass *p = pIt.getNext ();
210
Pass::TextureUnitStateIterator tuIt = p->getTextureUnitStateIterator ();
211
while (tuIt.hasMoreElements ())
213
TextureUnitState *tu = tuIt.getNext ();
215
const String texName (tu->getTextureName());
216
if (!imageLoaded && opt->ImageNameLoad &&
217
StringUtil::startsWith (texName, opt->image_filename))
219
// if it's an Image Texture mode
220
mTextures[channel] = texMgr->getByName (texName);
221
assert (!mTextures[channel].isNull() &&
222
String(texName + " is missing").c_str());
223
mBuffers[channel] = mTextures[channel]->getBuffer();
224
loadColorTexture (texName, channel);
228
else if (StringUtil::startsWith (texName, filename, false))
230
// if it's a dynamic texture updated by texture mode
231
// subtracts filename from texname
232
String texNameInfo = texName.substr (filename.size ());
233
//then split on Dot (in case of filename with dot in it.)
234
const StringVector texNameInfos =
235
StringUtil::split(texNameInfo, nameSep);
236
texType = texNameInfos[0];
238
if (texType == "Alpha")
240
mTextures[channel] = texMgr->getByName (texName);
241
assert (!mTextures[channel].isNull() &&
242
String(texName + " is missing").c_str());
243
mBuffers[channel] = mTextures[channel]->getBuffer();
244
loadAlphaTexture (texName, channel);
247
else if (texType == "Coverage")
249
mTextures[channel] = texMgr->getByName (texName);
250
assert (!mTextures[channel].isNull() &&
251
String(texName + " is missing").c_str());
252
mBuffers[channel] = mTextures[channel]->getBuffer();
253
loadColorTexture (texName, channel);
254
coverageLoaded = true;
257
else if (!lightLoaded && !mIsShaderShadowed
258
&& texType == "Light" )
260
mLightTexture = texMgr->getByName (texName);
261
assert (!mLightTexture.isNull() &&
262
String(texName + " is missing").c_str());
263
mLightBuffer = mLightTexture->getBuffer();
264
loadTexture (texName, mLightImage);
266
assert (mLightBuffer->getWidth () == mLightImage.getWidth () &&
267
mLightBuffer->getHeight () == mLightImage.getHeight ());
269
String shadowTexName (filename + nameSep + "HS");
270
for (size_t k = 1; k < texNameInfos.size(); k++)
271
shadowTexName += nameSep + texNameInfos[k];
272
if (ResourceGroupManager::getSingleton().
273
resourceExists (opt->groupName, shadowTexName))
275
loadTexture (shadowTexName, mShadow);
276
assert (mShadow.getWidth () == mLightImage.getWidth () &&
277
mShadow.getHeight () == mLightImage.getHeight ());
286
else if (!coverageLoaded && !baseLoaded && texType == "Base")
288
mTextures[channel] = texMgr->getByName (texName);
289
assert (!mTextures[channel].isNull() &&
290
String(texName + " is missing").c_str());
291
mBuffers[channel] = mTextures[channel]->getBuffer();
292
loadColorTexture (texName, channel);
299
for (unsigned int i = 0; i < mNumTexture; i++)
301
mNumChannelperTexture[i] = mImages[i].getBPP () / 8;
302
doTextureNeedUpdate[i] = false;
303
isTextureModified[i] = false;
308
//-----------------------------------------------------------------------
309
void PagingLandScapeTexture::setOptions(void)
311
PagingLandScapeOptions * const opt = mParent->getOptions();
312
String matClassName (
313
(opt->VertexCompression ?
314
String(mMaterialBaseName + "Decompress")
318
MaterialPtr material = MaterialManager::getSingleton().getByName (matClassName);
319
if (opt->VertexCompression && material.isNull())
321
matClassName = mMaterialBaseName;
322
opt->VertexCompression = false;
323
opt->lodMorph = false;
324
material = MaterialManager::getSingleton().getByName (matClassName);
326
assert (!material.isNull() &&
327
String(matClassName + "Must exists in the" + opt->groupName + "group").c_str ());
329
bool hasVertexProgram = false;
330
bool hasFragmentProgram = false;
332
Material::TechniqueIterator tIt = material->getTechniqueIterator ();
333
while (tIt.hasMoreElements ())
335
Technique * const t = tIt.getNext ();
336
Technique::PassIterator pIt = t->getPassIterator ();
337
while (pIt.hasMoreElements ())
339
Pass * const p = pIt.getNext ();
342
if ( p->hasVertexProgram ())
344
if (hasVertexProgram == false)
346
hasVertexProgram = p->hasVertexProgram ();
348
GpuProgramParametersSharedPtr params = p->getVertexProgramParameters();
351
GpuConstantDefinition const * const e = params->_findNamedConstantDefinition("splatSettings");
353
GpuProgramParameters::RealConstantEntry * const e = params->getNamedRealConstantEntry ("splatSettings");
362
if (hasFragmentProgram == false)
364
hasFragmentProgram = p->hasFragmentProgram ();
368
if (!hasVertexProgram)
370
opt->VertexCompression = false;
371
opt->lodMorph = false;
374
//-----------------------------------------------------------------------
375
bool PagingLandScapeTexture::isMaterialSupported(bool recursive)
377
const PagingLandScapeOptions * const opt = mParent->getOptions();
379
if (opt->VertexCompression && recursive)
381
const String MatClassName (mMaterialBaseName);
382
mMaterialBaseName = mMaterialBaseName + "Decompress";
383
const bool isOk = MaterialManager::getSingleton ().resourceExists (mMaterialBaseName) &&
384
isMaterialSupported(false);
385
mMaterialBaseName = MatClassName;
390
MaterialPtr material = MaterialManager::getSingleton().getByName (mMaterialBaseName);
391
assert (!material.isNull() &&
392
String(mMaterialBaseName + " Must exists in the" + opt->groupName + "group").c_str ());
394
unsigned short numPasses = 0;
396
//these will store the maximum number of texture units, alpha textures,
397
//coverage textures, etc. after iterating through all passes in the material
398
size_t numTextureUnits = 0;
399
size_t numAlphaTexture = 0;
400
size_t numCoverageTexture = 0;
401
size_t numSplats = 0;
402
unsigned int numDynamicTexture = 0;
405
size_t passNumTextureUnits;
406
size_t passNumAlphaTextures;
407
size_t passNumCoverageTextures;
408
size_t passNumSplats;
409
unsigned int passNumDynamicTextures;
411
bool needVertexProgram = false;
412
bool needFragmentProgram = false;
413
bool isImageMode = false;
414
bool isSplatMode = false;
415
bool isBaseMode = false;
417
Material::TechniqueIterator tIt = material->getTechniqueIterator ();
418
while (tIt.hasMoreElements ())
420
Technique * const t = tIt.getNext ();
421
numPasses = std::max (numPasses, t->getNumPasses());
422
Technique::PassIterator pIt = t->getPassIterator ();
423
while (pIt.hasMoreElements ())
426
passNumTextureUnits = 0;
427
passNumAlphaTextures = 0;
428
passNumCoverageTextures = 0;
430
passNumDynamicTextures = 0;
431
Pass * const p = pIt.getNext ();
432
if (needVertexProgram == false)
433
needVertexProgram = p->hasVertexProgram ();
434
if (needFragmentProgram == false)
435
needFragmentProgram = p->hasFragmentProgram ();
437
numTextureUnits = std::max<unsigned int>(static_cast<unsigned int>(numTextureUnits), static_cast<unsigned int>(p->getNumTextureUnitStates()));
439
numTextureUnits = std::max (numTextureUnits, p->getNumTextureUnitStates());
441
Pass::TextureUnitStateIterator tuIt = p->getTextureUnitStateIterator ();
442
while (tuIt.hasMoreElements ())
444
TextureUnitState * const tu = tuIt.getNext ();
445
const String texType (tu->getTextureName());
446
if (std::string::npos == texType.find("."))
448
// This Texture Name is A keyword,
449
// check how many are dynamic in this material
451
StringUtil::startsWith (texType, "base", true))
454
passNumDynamicTextures++;
456
else if (!isImageMode &&
457
StringUtil::startsWith (texType, "image", true))
460
passNumDynamicTextures++;
462
else if (texType == "Alpha" &&
463
StringUtil::startsWith (texType, "alpha", true))
466
passNumAlphaTextures++;
467
passNumDynamicTextures++;
469
else if (texType == "Coverage" &&
470
StringUtil::startsWith (texType, "coverage", true))
473
passNumDynamicTextures++;
474
passNumCoverageTextures++;
476
else if (texType == "Splatting" &&
477
StringUtil::startsWith (texType, "splatting", true))
482
else if (texType == "Light" &&
483
StringUtil::startsWith (texType, "light", true))
485
//dynamic light... but in software
488
else if (texType == "Horizon" &&
489
StringUtil::startsWith (texType, "horizon", true))
491
//dynamic light... but shader
492
mIsShaderShadowed = true;
498
if(passNumTextureUnits > numTextureUnits)
499
numTextureUnits = passNumTextureUnits;
501
numAlphaTexture += passNumAlphaTextures;
502
numCoverageTexture += passNumCoverageTextures;
503
numSplats += passNumSplats;
504
numDynamicTexture += passNumDynamicTextures;
508
if (isImageMode && !opt->ImageNameLoad)
510
if (opt->numTextureUnits < numTextureUnits)
512
if (needVertexProgram && opt->hasVertexShader == false)
514
if (needFragmentProgram && opt->hasFragmentShader == false)
517
if (isSplatMode && numAlphaTexture && opt->NumMatHeightSplat < numAlphaTexture)
520
// does all coverage must be 4 alpha ?
521
//if (isSplatMode && numCoverageTexture && opt->NumMatHeightSplat < numCoverageTexture * 4)
523
if (isSplatMode && numCoverageTexture && opt->NumMatHeightSplat < 4)
526
if (mIsShaderShadowed && !opt->hasFragmentShader2)
529
mIsSplatMode = isSplatMode;
530
mIsBaseMode = !mIsSplatMode && isBaseMode;
531
mNumTexture = (mParent->getOptions()->textureModifiable)? numDynamicTexture : 0;
534
//-----------------------------------------------------------------------
535
void PagingLandScapeTexture::_loadMaterial()
537
if (mMaterial.isNull())
539
const PagingLandScapeOptions * const opt = mParent->getOptions();
540
const String nameSep(".");
541
const String commonName (StringConverter::toString(mDataZ) +
542
nameSep + StringConverter::toString(mDataX));
543
if (opt->materialPerPage)
545
// JEFF - all material settings configured through material script
546
mMaterial = MaterialManager::getSingleton().getByName(
547
mMaterialBaseName + commonName);
551
const String filename (opt->LandScape_filename);
552
const bool compressed = opt->VertexCompression;
553
const String MatClassName (
555
String(mMaterialBaseName + "Decompress")
558
const String matname (MatClassName + nameSep
559
+ commonName + nameSep
561
mMaterial = MaterialManager::getSingleton().getByName(matname);
562
if (mMaterial.isNull())
564
mMaterial = MaterialManager::getSingleton().getByName(MatClassName);
565
assert (!mMaterial.isNull() &&
566
String(MatClassName + "Must exists in the" + opt->groupName + "group").c_str ());
567
mMaterial = mMaterial->clone(matname);
568
const String extName (opt->TextureExtension);
569
const String beginName (filename + nameSep);
570
const String endName (nameSep + commonName +
573
String texName, finalTexName;
574
unsigned int channel = 0;
575
unsigned int splat = 0;
577
unsigned int alphachannel = 0;
578
unsigned int coveragechannel = 0;
580
Material::TechniqueIterator tIt = mMaterial->getTechniqueIterator ();
581
while (tIt.hasMoreElements ())
587
Technique * const t = tIt.getNext ();
588
Technique::PassIterator pIt = t->getPassIterator ();
589
while (pIt.hasMoreElements ())
591
Pass * const p = pIt.getNext ();
592
Pass::TextureUnitStateIterator tuIt = p->getTextureUnitStateIterator ();
593
while (tuIt.hasMoreElements ())
595
TextureUnitState * const tu = tuIt.getNext ();
596
const String texType (tu->getTextureName());
597
if (std::string::npos == texType.find("."))
599
// This Texture Name is A keyword,
600
// meaning we have to dynamically replace it
602
// check by what texture to replace keyword
603
if (StringUtil::startsWith (texType, "image", true))
605
texName = opt->image_filename + endName;
608
else if (StringUtil::startsWith (texType, "splatting", true))
610
texName = opt->SplatDetailMapNames[splat % opt->NumMatHeightSplat];
613
else if (StringUtil::startsWith (texType, "base", true))
615
texName = beginName + texType + endName;
619
else if (StringUtil::startsWith (texType, "alpha", true))
621
texName = beginName + texType + nameSep +
622
StringConverter::toString(alphachannel) + endName;
627
else if (StringUtil::startsWith (texType, "coverage", true))
629
texName = beginName + texType + nameSep +
630
StringConverter::toString((coveragechannel * 4) % opt->NumMatHeightSplat) + endName;
635
else if (StringUtil::startsWith (texType, "light", true))
637
texName = beginName + texType + endName + extName;
639
else if (StringUtil::startsWith (texType, "horizon", true))
641
texName = beginName + "HSP" + endName + extName;
642
mPositiveShadow = true;
646
if(opt->Deformable &&
647
ResourceGroupManager::getSingleton().resourceExists(
649
texName + "modif." + extName))
651
finalTexName = texName + "modif." + extName;
655
finalTexName = texName + extName;
660
finalTexName = texName;
662
tu->setTextureName (finalTexName);
671
//-----------------------------------------------------------------------
672
void PagingLandScapeTexture::_unloadMaterial()
677
//-----------------------------------------------------------------------
678
void PagingLandScapeTexture::load(unsigned int x, unsigned int z)
680
if (!mIsLoaded && isMaterialSupported())
687
const PagingLandScapeOptions * const opt = mParent->getOptions();
688
mMaterial->setLightingEnabled (opt->lit);
689
mMaterial->setLodLevels (opt->lodMaterialDistanceList);
690
mMaterial->setReceiveShadows (true);
691
// If vertex shader, have to bind parameters
692
bindCompressionSettings ();
694
// load texture in main memory if we want to update it Real-Time
695
loadTexturesToModify();
701
//-----------------------------------------------------------------------
702
void PagingLandScapeTexture::unload()
706
if (mIsModified && mParent->getOptions()->saveDeformation)
709
if (!mMaterial.isNull())
712
for (unsigned int i = 0; i < mNumTexture; i++)
714
doTextureNeedUpdate[i] = false;
715
isTextureModified[i] = false;
716
mBuffers[i].setNull ();
717
mTextures[i].setNull ();
718
mImages[i].loadDynamicImage (0, 0, 0, 1, PF_R8G8B8A8, true, 1, 0);
720
// Anyway, they're surely null already, as they're freed by delete page()
724
const String resourceName (mMaterial->getName ());
726
assert (!mMaterial.isNull() && "PagingLandScapeTexture::unload");
729
///ember change start
730
///don't remove from the manager, since it's tricky to add it again it later on
731
// MaterialManager::getSingleton().remove (resourceName);
738
//-----------------------------------------------------------------------
739
void PagingLandScapeTexture::_save(void)
741
assert (!mMaterial.isNull() && "PagingLandScapeTexture::::_save");
743
const PagingLandScapeOptions * const opt = mParent->getOptions();
744
if (mNumTexture > 0 && opt->textureModifiable)
746
const String extname (opt->TextureExtension);
747
for (unsigned int i = 0; i < mNumTexture; i++)
749
if (isTextureModified[i])
751
String texName = mTextures[i]->getName ();
753
FileInfoListPtr finfo = ResourceGroupManager::getSingleton().findResourceFileInfo (
754
opt->groupName, texName);
755
FileInfoList::iterator it = finfo->begin();
756
if (it != finfo->end())
758
char *olddir = ChangeToDir (const_cast< char * > (((it)->archive->getName()).c_str()));
759
//FileSystemArchive::pushDirectory()
761
assert (mImages[i].getData ());
762
// check if we have to add modif to the name.
763
const String baseTexName (texName, 0, texName.size () - extname.size());
764
if (!StringUtil::endsWith (baseTexName, "modif."))
766
texName = baseTexName + "modif." + extname;
768
mImages[i].save (texName);
770
RetablishDir (olddir);
771
//FileSystemArchive::popDirectory();
773
} // if (it != finfo->end())
774
} // if (doTextureNeedUpdate[i])
775
} // for (unsigned int i = 0; i < mNumTexture; i++)
778
//-----------------------------------------------------------------------
779
void PagingLandScapeTexture::upload(const Image::Box& textureRect)
781
assert (mNumTexture > 0);
782
assert (!mMaterial.isNull() && "PagingLandScapeTexture::update()");
784
for (unsigned int i = 0; i < mNumTexture; i++)
786
if (doTextureNeedUpdate[i])
788
assert (!mTextures[i].isNull() && "PagingLandScapeTexture::update()");
789
assert (!mBuffers[i].isNull() && "PagingLandScapeTexture::update()");
790
assert (mImages[i].getData () != 0 && "PagingLandScapeTexture::update()");
792
const PixelBox srcBox = mImages[i].getPixelBox().getSubVolume(textureRect);
793
const PixelBox lock = mBuffers[i]->lock(textureRect, HardwareBuffer::HBL_DISCARD);
794
PixelUtil::bulkPixelConversion(srcBox, lock);
795
mBuffers[i]->unlock();
797
doTextureNeedUpdate[i] = false;
798
isTextureModified[i] = true;
800
//#define _Missed_Spot
803
// debug can help finding missed spot.
804
const PixelBox srcSpotBox = mImages[i].getPixelBox();
805
const unsigned int textureSize = (mParent->getOptions()->PageSize - 1) *
806
mParent->getOptions()->TextureStretchFactor;
807
const Image::Box rect (0, 0, 0, textureSize, textureSize, 1);
808
const PixelBox lockSpot = mBuffers[i]->lock (rect ,HardwareBuffer::HBL_DISCARD);
809
PixelUtil::bulkPixelConversion(srcSpotBox, lockSpot);
810
mBuffers[i]->unlock();
811
#endif //_Missed_Spot
815
//-----------------------------------------------------------------------
816
bool PagingLandScapeTexture::isLoaded() const
820
//-----------------------------------------------------------------------
821
const MaterialPtr& PagingLandScapeTexture::getMaterial() const
825
//-----------------------------------------------------------------------
826
void PagingLandScapeTexture::loadAlphaTexture(const String &filename, const unsigned int channel)
828
assert (mNumTexture > 0);
829
if (mImages[channel].getData () == 0)
832
Imageloader.load(filename, mParent->getOptions()->groupName);
833
const size_t size = Imageloader.getSize();
834
uchar *data = new uchar [size];
835
memcpy (data, Imageloader.getData(), size*sizeof(uchar));
836
mImages[channel].loadDynamicImage(data,
837
Imageloader.getWidth(), Imageloader.getHeight(),
838
1, PF_A8, true, 1, 0);
841
assert (mImages[channel].getHeight() == mImages[channel].getWidth());
842
assert (mImages[channel].getHeight() / (mParent->getOptions()->PageSize - 1)
843
== mParent->getOptions()->TextureStretchFactor &&
844
String("(texture size / (pagesize-1)) and texture stretch factor defined in terrain config file doesn't fit.").c_str());
846
//-----------------------------------------------------------------------
847
void PagingLandScapeTexture::loadColorTexture(const String &filename, const unsigned int channel)
849
assert (mNumTexture > 0);
851
loadTexture (filename, mImages[channel]);
853
assert (mImages[channel].getHeight() == mImages[channel].getWidth());
854
assert (mImages[channel].getHeight() / (mParent->getOptions()->PageSize - 1)
855
== mParent->getOptions()->TextureStretchFactor &&
856
String("(texture size / (pagesize-1)) and texture stretch factor defined in terrain config file doesn't fit.").c_str());
858
//-----------------------------------------------------------------------
859
void PagingLandScapeTexture::loadTexture(const String &filename, Image &img)
861
if (img.getData () == 0)
863
img.load(filename, mParent->getOptions()->groupName);
866
//-----------------------------------------------------------------------
867
void PagingLandScapeTexture::updated ()
870
mPaintRect.right = 0;
872
mPaintRect.bottom = 0;
873
mIsPaintRectModified = false;
875
mDeformRect.left = 0;
876
mDeformRect.right = 0;
878
mDeformRect.bottom = 0;
879
mIsDeformRectModified = false;
881
//-----------------------------------------------------------------------
882
void PagingLandScapeTexture::compute(
883
PagingLandScapeData2D* data,
884
const Image::Box& dataRect,
885
const Image::Box& textureRect)
887
assert (mNumTexture > 0);
888
const size_t heightfiledsize = mParent->getOptions()->PageSize - 1;
889
const Real textureScale = mParent->getOptions()->TextureStretchFactor;
890
const unsigned int textureSize = static_cast<unsigned int>(heightfiledsize * textureScale);
891
unsigned int curr_image_pos = static_cast <unsigned int>(textureRect.top*textureSize + textureRect.left);
892
const unsigned int image_width = static_cast <unsigned int>((textureSize - (textureRect.right - textureRect.left)));
893
const Real inv_scale = 1 / textureScale;
895
const Real * const ogre_restrict heightData = data->getHeightData ();
896
assert (heightData && "PagingLandScapeTexture::compute()");
898
for (size_t k = textureRect.top; k < textureRect.bottom; ++k)
900
const unsigned int k_terrain = (unsigned int)(k * inv_scale);
901
const size_t curr_row = k_terrain * heightfiledsize;
902
for (size_t i = textureRect.left; i < textureRect.right; ++i)
904
const unsigned int i_terrain = (unsigned int)(i * inv_scale);
906
assert (i < textureSize && k < textureSize &&
907
"PagingLandScapeTexture::compute()");
909
assert (i_terrain < heightfiledsize && k_terrain < heightfiledsize &&
910
"PagingLandScapeTexture::compute()");
913
computePointAlpha(curr_image_pos,
914
heightData[i_terrain + curr_row],
915
1.0f - data->getNormal (i_terrain, k_terrain).y);
917
computePointColor (curr_image_pos,
918
heightData[i_terrain + curr_row],
919
1.0f - data->getNormal (i_terrain, k_terrain).y);
923
curr_image_pos += image_width;
926
//-----------------------------------------------------------------------
927
void PagingLandScapeTexture::paint (const unsigned int xParam,
928
const unsigned int zParam,
929
const Real paintForce)
931
assert (mNumTexture > 0);
932
assert (paintForce >= 0.0f && paintForce <= 1.0f && "PagingLandScapeTexture::paint()");
933
const Real blend = paintForce;
935
const size_t psize = mParent->getOptions()->PageSize - 1;
936
const Real textureScale = mParent->getOptions ()->TextureStretchFactor;
937
const unsigned int textureScaleCount = static_cast <unsigned int> (textureScale);
939
assert (((xParam + zParam * psize) < psize*psize) && "PagingLandScapeTexture::paint()");
941
const unsigned int xScaled = xParam * textureScaleCount;
942
const unsigned int zScaled = zParam * textureScaleCount;
943
const size_t pSizeScaled = psize * textureScaleCount;
945
for (unsigned int j = 0; j < textureScaleCount; j++)
947
const unsigned int z = zScaled + j;
950
const unsigned int zShift = z * pSizeScaled;
951
for (unsigned int k = 0; k < textureScaleCount; k++)
953
const unsigned int x = xScaled + k;
956
const unsigned int curr_image_pos = x + zShift;
957
assert (curr_image_pos < pSizeScaled*pSizeScaled);
958
paintPoint (curr_image_pos, blend);
959
adjustPaintRectangle (x, z);
965
//-----------------------------------------------------------------------
966
void PagingLandScapeTexture::update()
968
assert (mNumTexture > 0);
969
// at least deformed once, so need to save texture if asked by user (option)
972
Image::Box dataRect (0, 0, 0, 0, 0, 1);
973
Image::Box texturerect (0, 0, 0, 0, 0, 1);
975
// computes deformation
976
PagingLandScapeData2D *data = 0;
977
if (mIsDeformRectModified)
979
dataRect = mDeformRect;
980
data = mParent->getSceneManager()->getData2DManager()->getData2D(mDataX, mDataZ);
982
if (dataRect.getWidth() && dataRect.getHeight ())
985
const Real textureScale = mParent->getOptions()->TextureStretchFactor;
987
texturerect.left = static_cast<size_t>(dataRect.left * textureScale);
988
texturerect.top = static_cast<size_t>(dataRect.top * textureScale);
989
texturerect.right = static_cast<size_t>(dataRect.right * textureScale + 1);
990
texturerect.bottom = static_cast<size_t>(dataRect.bottom * textureScale + 1);
993
dataRect.bottom += 1;
994
compute(data, dataRect, texturerect);
997
// try to upload only the smallest rectangle containing modification
998
if (mIsPaintRectModified)
1000
if (mIsDeformRectModified)
1002
texturerect.left = std::min (mPaintRect.left, dataRect.left);
1003
texturerect.right = std::max (mPaintRect.right, dataRect.right);
1004
texturerect.top = std::min (mPaintRect.top, dataRect.top);
1005
texturerect.bottom = std::max (mPaintRect.bottom, dataRect.bottom);
1009
texturerect = mPaintRect;
1011
texturerect.right += 1;
1012
texturerect.bottom += 1;
1014
} // if (mIsRectModified)
1017
// Upload any changes (deformation or)
1018
if (texturerect.getWidth() && texturerect.getHeight ())
1020
upload (texturerect);
1021
} // if (texturerect.getWidth() && texturerect.getHeight ())
1023
if (mIsDeformRectModified)
1024
data->resetDeformationRectangle ();
1025
PagingLandScapeTexture::updated ();
1028
//-----------------------------------------------------------------------
1029
bool PagingLandScapeTexture::needUpdate () const
1031
return mIsDeformRectModified || mIsPaintRectModified;
1033
//-----------------------------------------------------------------------
1034
void PagingLandScapeTexture::adjustDeformationRectangle(unsigned int x, unsigned int z)
1036
assert (mNumTexture > 0);
1037
assert (x < (mParent->getOptions ()->PageSize));
1038
assert (z < (mParent->getOptions ()->PageSize));
1040
if (mIsDeformRectModified)
1042
if (mDeformRect.left > x)
1043
mDeformRect.left = x;
1044
if (mDeformRect.right < x)
1045
mDeformRect.right = x;
1047
if (mDeformRect.top > z)
1048
mDeformRect.top = z;
1049
if (mDeformRect.bottom < z)
1050
mDeformRect.bottom = z;
1054
// first modification :
1055
// deformation rectangle is the point
1056
mDeformRect.left = x;
1057
mDeformRect.right = x;
1058
mDeformRect.top = z;
1059
mDeformRect.bottom = z;
1060
mIsDeformRectModified = true;
1063
//-----------------------------------------------------------------------
1064
void PagingLandScapeTexture::adjustPaintRectangle(unsigned int x, unsigned int z)
1066
assert (mNumTexture > 0);
1067
assert (x < ((mParent->getOptions ()->PageSize - 1) * mParent->getOptions ()->TextureStretchFactor));
1068
assert (z < ((mParent->getOptions ()->PageSize - 1) * mParent->getOptions ()->TextureStretchFactor));
1070
if (mIsPaintRectModified)
1072
if (mPaintRect.left > x)
1073
mPaintRect.left = x;
1074
else if (mPaintRect.right < x)
1075
mPaintRect.right = x;
1077
if (mPaintRect.top > z)
1079
else if (mPaintRect.bottom < z)
1080
mPaintRect.bottom = z;
1084
// first modification :
1085
// deformation rectangle is the point
1086
mPaintRect.left = x;
1087
mPaintRect.right = x;
1089
mPaintRect.bottom = z;
1090
mIsPaintRectModified = true;
1093
//-----------------------------------------------------------------------
1094
void PagingLandScapeTexture::lightUpdate()
1096
PagingLandScapeOptions * const opt = mParent->getOptions();
1097
if (mIsShaderShadowed)
1099
const Real SunAngle = opt->SunAngle;
1100
const Vector3 SunDir = opt->Sun;
1102
const bool positiveHorizon = (SunDir.y > 0);// Sun is west (true), east (false);
1103
assert (fabs (SunAngle) < 1.1f);
1105
const Real LightAngle = (positiveHorizon)? SunAngle : -SunAngle;
1106
if (positiveHorizon != mPositiveShadow)
1108
const String texname (opt->LandScape_filename
1110
((positiveHorizon)? String(".HSP.") : String(".HSN."))
1112
StringConverter::toString(mDataZ) +
1114
StringConverter::toString(mDataX) + "." +
1115
opt->TextureExtension);
1116
mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(2)->setTextureName (texname);
1117
mPositiveShadow = positiveHorizon;
1119
GpuProgramParametersSharedPtr params = mMaterial->getBestTechnique()->getPass(0)->getFragmentProgramParameters();
1121
params->setNamedConstant("HorizonSettings", Vector4(SunDir.x, SunDir.y, SunDir.z, LightAngle));
1123
GpuProgramParameters::RealConstantEntry * const e = params->getNamedRealConstantEntry ("HorizonSettings");
1125
e->val[0] = static_cast <float> (SunDir.x);
1126
e->val[1] = static_cast <float> (SunDir.y);
1127
e->val[2] = static_cast <float> (SunDir.z);
1128
e->val[3] = static_cast <float> (LightAngle);
1132
else if (mIsShadowed)
1134
assert (mLightImage.getData ());
1138
const PixelBox srcBox = mLightImage.getPixelBox();
1139
const unsigned int mTextureSize = static_cast<unsigned int>(mParent->mPageSize * opt->TextureStretchFactor);
1140
const Image::Box rect (0, 0, 0, mTextureSize, mTextureSize, 1);
1141
const PixelBox lock = mLightBuffer->lock (rect , HardwareBuffer::HBL_DISCARD);
1142
PixelUtil::bulkPixelConversion(srcBox, lock);
1143
mLightBuffer->unlock();
1146
//-----------------------------------------------------------------------
1147
void PagingLandScapeTexture::computeLightMap () const
1149
assert(mIsShadowed);
1150
PagingLandScapeOptions * const opt = mParent->getOptions();
1151
const Vector3 LightDir = opt->Sun;
1152
const Real SunAngle = opt->SunAngle;
1154
const bool positiveHorizon = (LightDir.y > 0);// Sun is west (true), east (false);
1155
assert (fabs (SunAngle) < 1.1f);
1157
const Real LightAngle = (positiveHorizon)? SunAngle : -SunAngle;
1158
const size_t offsetneg = (positiveHorizon)? 0: 1;
1159
//const Real LightAngle = SunAngle;
1162
unsigned int curr_rowY = 0;
1163
const uchar BScale = 255;
1164
const Real uchardivider = 1.0f / BScale;
1165
unsigned int curr_image_pos = 0;
1166
uchar * const ogre_restrict lightmap = (uchar *) (mLightImage.getData ());
1167
const uchar * const ogre_restrict HorizonAngle = mShadow.getData();
1169
const unsigned int mTextureSize = (unsigned int) mLightImage.getWidth ();
1170
assert ((mShadow.getBPP ()) / 8 == 3);
1171
const unsigned int rowpitch = mTextureSize*3;
1172
for(unsigned int nZ = 0; nZ < mTextureSize ; nZ++)
1174
unsigned int curr_image_posX = 0;
1175
for(unsigned int nX = 0; nX < mTextureSize; nX++)
1177
const unsigned int nVert = static_cast <unsigned int> (curr_rowY + curr_image_posX + offsetneg);
1178
const Real hAngle = HorizonAngle[nVert] * uchardivider;
1179
if (hAngle < LightAngle)
1181
const Real intensity = 1 - (LightAngle - hAngle);
1182
if (intensity > 0.0f)
1184
//intensity *= std::max(LightDir.dotProduct (data->getNormal (nX, nZ)), 0.0f);
1185
lightmap[curr_image_pos] = static_cast <uchar> (intensity * BScale);
1190
// totally in shadow
1191
lightmap[curr_image_pos] = 0;
1196
// if Vertex is lighted
1197
const Real intensity = BScale;
1198
//const Real intensity = BScale * std::min(1.0f, LightDir.dotProduct (data->getNormal (nX, nZ)));
1199
lightmap[curr_image_pos] = static_cast <uchar> (intensity);
1201
// if colored light should use a rgb map..
1204
curr_image_posX += 3;
1206
curr_rowY += rowpitch;
1210
//-----------------------------------------------------------------------
1211
void PagingLandScapeTexture::computePointAlpha(
1212
const unsigned int imagePos,
1216
assert (mNumTexture > 0);
1217
const unsigned int numHeights = mParent->getOptions()->NumMatHeightSplat;
1218
unsigned int indx = 1;
1219
while (indx < (numHeights - 1) && height >= mParent->heights[indx])
1222
const unsigned int bScale = 255;
1223
const unsigned int up_indx = indx;
1224
const unsigned int down_indx = indx - 1;
1225
const Real interpol = (height - mParent->heights[down_indx])
1226
* mParent->dividers[up_indx];
1228
std::vector<Real> alpha;
1229
alpha.reserve(numHeights);
1230
alpha.resize(numHeights);
1231
for (unsigned int ialpha = 0; ialpha < numHeights; ialpha++)
1233
alpha[ialpha] = 0.0f;
1236
if (slope < 0.05f)// speed-up as it's invisible
1238
const Real B = (1.0f - interpol);
1239
const Real C = interpol;
1241
alpha[indx - 1] = B;
1246
const Real A = (1.0f - slope);
1247
const Real B = A * (1.0f - interpol);
1248
const Real C = A * interpol;
1249
const Real D = slope;
1251
alpha[indx - 1] = B;
1254
alpha[ 2 ] = alpha[ 2 ] + slope;
1255
alpha[ 2 ] = alpha[ 2 ] > 1.0f ? 1.0f : alpha[ 2 ];
1257
// save changes in textures
1259
unsigned int currChannel = 0;
1260
for (unsigned int k = 0; k < mNumTexture; k++)
1262
if (mImages[k].getBPP () == 8)
1264
uchar * const BaseData = mImages[k].getData ();
1265
assert (BaseData && "PagingLandScapeTexture::computePointAlpha()");
1266
const unsigned int curr_image_pos = imagePos*(static_cast <unsigned int>(mNumChannelperTexture[k]));
1267
assert (mNumChannelperTexture[k] == (mImages[k].getBPP ()/8));
1268
for (unsigned int j = 0; j < mNumChannelperTexture[k]; j++)
1270
BaseData[ curr_image_pos + j] = static_cast <uchar> (alpha[currChannel]*bScale);
1277
//-----------------------------------------------------------------------
1278
void PagingLandScapeTexture::computePointColor(
1279
const unsigned int imagePos,
1283
assert (mNumTexture > 0);
1284
const unsigned int numHeights = mParent->getOptions()->NumMatHeightSplat;
1286
unsigned int indx = 1;
1287
while (indx < (numHeights - 1) && height >= mParent->heights[indx])
1290
const unsigned int bScale = 255;
1291
const unsigned int up_indx = indx;
1292
const unsigned int down_indx = indx - 1;
1293
const Real interpol = (height - mParent->heights[down_indx])
1294
* mParent->dividers[up_indx];
1296
//ColourValue color;
1297
std::vector<ColourValue> color;
1298
for (unsigned int itex = 0; itex < mNumTexture; itex++)
1300
for (unsigned int ichan = 0; ichan < mNumChannelperTexture[itex]; ichan++)
1302
color.push_back (ColourValue::Black);
1308
unsigned int currTexture = 0;
1311
if (indx < mNumChannelperTexture[currTexture])
1313
indx = indx - mNumChannelperTexture[currTexture];
1316
currTexture = currTexture < mNumTexture ? currTexture : mNumTexture - 1;
1318
if (slope < 0.05f)// speed-up as it's invisible
1320
const Real B = (1.0f - interpol);
1321
const Real C = interpol;
1322
color[currTexture] = mParent->colors[down_indx] * B + mParent->colors[up_indx] * C;
1326
const Real A = (1.0f - slope);
1327
const Real B = A * (1.0f - interpol);
1328
const Real C = A * interpol;
1329
const Real D = slope;
1331
color[currTexture] = mParent->colors[down_indx] * B + mParent->colors[up_indx] * C + mParent->colors[2] * D;
1333
// save changes in textures
1334
unsigned int currChannel = 0;
1335
for (unsigned int k = 0; k < mNumTexture; k++)
1337
if (mImages[k].getBPP () > 8)
1339
uchar * const BaseData = mImages[k].getData ();
1340
assert (BaseData && "PagingLandScapeTexture::computePointColor()");
1341
const unsigned int curr_image_pos = imagePos*(static_cast <unsigned int>(mNumChannelperTexture[k]));
1342
assert (mNumChannelperTexture[k] == (mImages[k].getBPP ()/8));
1344
BaseData[ curr_image_pos + 0] = static_cast <uchar> (color[k].r * bScale);
1345
BaseData[ curr_image_pos + 1] = static_cast <uchar> (color[k].g * bScale);
1346
BaseData[ curr_image_pos + 2] = static_cast <uchar> (color[k].b * bScale);
1351
//-----------------------------------------------------------------------
1352
void PagingLandScapeTexture::paintPoint (const unsigned int imagePos,
1353
const Real paintForce)
1355
assert (mNumTexture > 0);
1356
assert(mParent->channelModifList);
1357
const std::vector<Real> *channelModifList = mParent->channelModifList;
1358
const uchar bScale = 255;
1359
const Real invPaintForce = 1.0f - paintForce;
1360
unsigned int currChannel = 0;
1361
for (unsigned int k = 0; k < mNumTexture; k++)
1363
uchar * const BaseData = mImages[k].getData();
1364
assert (BaseData && "PagingLandScapeTexture::paint()");
1365
const unsigned int currImagePos = imagePos * mNumChannelperTexture[k];
1366
assert (currImagePos < mImages[k].getSize ());
1367
assert (mNumChannelperTexture[k]*8 == mImages[k].getBPP ());
1369
for (unsigned int j = 0; j < mNumChannelperTexture[k]; j++)
1371
BaseData[ currImagePos + j ] =
1372
static_cast <uchar> (
1373
((*channelModifList)[currChannel]) * paintForce * bScale
1374
+ BaseData[ currImagePos + j ] * invPaintForce
1378
doTextureNeedUpdate[k] = true;