mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-30 09:36:43 +00:00
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
e03e2f0817
10 changed files with 143 additions and 90 deletions
|
@ -988,7 +988,7 @@ void RenderingManager::updateWaterRippleEmitterPtr (const MWWorld::Ptr& old, con
|
||||||
|
|
||||||
void RenderingManager::frameStarted(float dt, bool paused)
|
void RenderingManager::frameStarted(float dt, bool paused)
|
||||||
{
|
{
|
||||||
if (mTerrain && mTerrain->getVisible())
|
if (mTerrain)
|
||||||
mTerrain->update(mRendering.getCamera()->getRealPosition());
|
mTerrain->update(mRendering.getCamera()->getRealPosition());
|
||||||
|
|
||||||
if (!paused)
|
if (!paused)
|
||||||
|
|
|
@ -466,6 +466,18 @@ namespace MWWorld
|
||||||
ESM::Land *ptr = new ESM::Land();
|
ESM::Land *ptr = new ESM::Land();
|
||||||
ptr->load(esm);
|
ptr->load(esm);
|
||||||
|
|
||||||
|
// Same area defined in multiple plugins? -> last plugin wins
|
||||||
|
// Can't use search() because we aren't sorted yet - is there any other way to speed this up?
|
||||||
|
for (std::vector<ESM::Land*>::iterator it = mStatic.begin(); it != mStatic.end(); ++it)
|
||||||
|
{
|
||||||
|
if ((*it)->mX == ptr->mX && (*it)->mY == ptr->mY)
|
||||||
|
{
|
||||||
|
delete *it;
|
||||||
|
mStatic.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mStatic.push_back(ptr);
|
mStatic.push_back(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,6 +153,14 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
|
||||||
// That should be it, I haven't seen any other fields yet.
|
// That should be it, I haven't seen any other fields yet.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NAM0 sometimes appears here, sometimes further on
|
||||||
|
ref.mNam0 = 0;
|
||||||
|
if (esm.isNextSub("NAM0"))
|
||||||
|
{
|
||||||
|
esm.getHT(ref.mNam0);
|
||||||
|
//esm.getHNOT(NAM0, "NAM0");
|
||||||
|
}
|
||||||
|
|
||||||
esm.getHNT(ref.mRefnum, "FRMR");
|
esm.getHNT(ref.mRefnum, "FRMR");
|
||||||
ref.mRefID = esm.getHNString("NAME");
|
ref.mRefID = esm.getHNString("NAME");
|
||||||
|
|
||||||
|
@ -243,7 +251,6 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
|
||||||
// Update: Well, maybe not completely useless. This might actually be
|
// Update: Well, maybe not completely useless. This might actually be
|
||||||
// number_of_references + number_of_references_moved_here_Across_boundaries,
|
// number_of_references + number_of_references_moved_here_Across_boundaries,
|
||||||
// and could be helpful for collecting these weird moved references.
|
// and could be helpful for collecting these weird moved references.
|
||||||
ref.mNam0 = 0;
|
|
||||||
if (esm.isNextSub("NAM0"))
|
if (esm.isNextSub("NAM0"))
|
||||||
{
|
{
|
||||||
esm.getHT(ref.mNam0);
|
esm.getHT(ref.mNam0);
|
||||||
|
|
|
@ -40,29 +40,6 @@ namespace Terrain
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MaterialGenerator::getMaxLayersPerPass ()
|
|
||||||
{
|
|
||||||
// count the texture units free
|
|
||||||
Ogre::uint8 freeTextureUnits = 16;
|
|
||||||
|
|
||||||
// first layer doesn't need blendmap
|
|
||||||
--freeTextureUnits;
|
|
||||||
|
|
||||||
if (mSplitShadows)
|
|
||||||
freeTextureUnits -= 3;
|
|
||||||
else if (mShadows)
|
|
||||||
--freeTextureUnits;
|
|
||||||
|
|
||||||
// each layer needs 1.25 units (1xdiffusespec, 0.25xblend)
|
|
||||||
return static_cast<Ogre::uint8>(freeTextureUnits / (1.25f)) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MaterialGenerator::getRequiredPasses ()
|
|
||||||
{
|
|
||||||
int maxLayersPerPass = getMaxLayersPerPass();
|
|
||||||
return std::max(1.f, std::ceil(static_cast<float>(mLayerList.size()) / maxLayersPerPass));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ogre::MaterialPtr MaterialGenerator::generate(Ogre::MaterialPtr mat)
|
Ogre::MaterialPtr MaterialGenerator::generate(Ogre::MaterialPtr mat)
|
||||||
{
|
{
|
||||||
return create(mat, false, false);
|
return create(mat, false, false);
|
||||||
|
@ -201,45 +178,64 @@ namespace Terrain
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
int numPasses = getRequiredPasses();
|
bool shadows = mShadows && !renderCompositeMap;
|
||||||
assert(numPasses);
|
|
||||||
int maxLayersInOnePass = getMaxLayersPerPass();
|
|
||||||
|
|
||||||
for (int pass=0; pass<numPasses; ++pass)
|
int layerOffset = 0;
|
||||||
|
while (layerOffset < (int)mLayerList.size())
|
||||||
{
|
{
|
||||||
int layerOffset = maxLayersInOnePass * pass;
|
int blendmapOffset = (layerOffset == 0) ? 1 : 0; // the first layer of the first pass is the base layer and does not need a blend map
|
||||||
int blendmapOffset = (pass == 0) ? 1 : 0; // the first layer of the first pass is the base layer and does not need a blend map
|
|
||||||
|
// Check how many layers we can fit in this pass
|
||||||
|
int numLayersInThisPass = 0;
|
||||||
|
int numBlendTextures = 0;
|
||||||
|
std::vector<std::string> blendTextures;
|
||||||
|
int remainingTextureUnits = OGRE_MAX_TEXTURE_LAYERS;
|
||||||
|
if (shadows)
|
||||||
|
remainingTextureUnits -= (mSplitShadows ? 3 : 1);
|
||||||
|
while (remainingTextureUnits && layerOffset + numLayersInThisPass < (int)mLayerList.size())
|
||||||
|
{
|
||||||
|
int layerIndex = numLayersInThisPass + layerOffset;
|
||||||
|
|
||||||
|
int neededTextureUnits=0;
|
||||||
|
int neededBlendTextures=0;
|
||||||
|
|
||||||
|
if (layerIndex != 0)
|
||||||
|
{
|
||||||
|
std::string blendTextureName = mBlendmapList[getBlendmapIndexForLayer(layerIndex)]->getName();
|
||||||
|
if (std::find(blendTextures.begin(), blendTextures.end(), blendTextureName) == blendTextures.end())
|
||||||
|
{
|
||||||
|
blendTextures.push_back(blendTextureName);
|
||||||
|
++neededBlendTextures;
|
||||||
|
++neededTextureUnits; // blend texture
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++neededTextureUnits; // layer texture
|
||||||
|
if (neededTextureUnits <= remainingTextureUnits)
|
||||||
|
{
|
||||||
|
// We can fit another!
|
||||||
|
remainingTextureUnits -= neededTextureUnits;
|
||||||
|
numBlendTextures += neededBlendTextures;
|
||||||
|
++numLayersInThisPass;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break; // We're full
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
sh::MaterialInstancePass* p = material->createPass ();
|
sh::MaterialInstancePass* p = material->createPass ();
|
||||||
|
|
||||||
p->setProperty ("vertex_program", sh::makeProperty<sh::StringValue>(new sh::StringValue("terrain_vertex")));
|
p->setProperty ("vertex_program", sh::makeProperty<sh::StringValue>(new sh::StringValue("terrain_vertex")));
|
||||||
p->setProperty ("fragment_program", sh::makeProperty<sh::StringValue>(new sh::StringValue("terrain_fragment")));
|
p->setProperty ("fragment_program", sh::makeProperty<sh::StringValue>(new sh::StringValue("terrain_fragment")));
|
||||||
if (pass != 0)
|
if (layerOffset != 0)
|
||||||
{
|
{
|
||||||
p->setProperty ("scene_blend", sh::makeProperty(new sh::StringValue("alpha_blend")));
|
p->setProperty ("scene_blend", sh::makeProperty(new sh::StringValue("alpha_blend")));
|
||||||
// Only write if depth is equal to the depth value written by the previous pass.
|
// Only write if depth is equal to the depth value written by the previous pass.
|
||||||
p->setProperty ("depth_func", sh::makeProperty(new sh::StringValue("equal")));
|
p->setProperty ("depth_func", sh::makeProperty(new sh::StringValue("equal")));
|
||||||
}
|
}
|
||||||
|
|
||||||
p->mShaderProperties.setProperty ("is_first_pass", sh::makeProperty(new sh::BooleanValue(pass == 0)));
|
|
||||||
p->mShaderProperties.setProperty ("render_composite_map", sh::makeProperty(new sh::BooleanValue(renderCompositeMap)));
|
p->mShaderProperties.setProperty ("render_composite_map", sh::makeProperty(new sh::BooleanValue(renderCompositeMap)));
|
||||||
p->mShaderProperties.setProperty ("display_composite_map", sh::makeProperty(new sh::BooleanValue(displayCompositeMap)));
|
p->mShaderProperties.setProperty ("display_composite_map", sh::makeProperty(new sh::BooleanValue(displayCompositeMap)));
|
||||||
|
|
||||||
Ogre::uint numLayersInThisPass = std::min(maxLayersInOnePass, (int)mLayerList.size()-layerOffset);
|
|
||||||
|
|
||||||
// a blend map might be shared between two passes
|
|
||||||
Ogre::uint numBlendTextures=0;
|
|
||||||
std::vector<std::string> blendTextures;
|
|
||||||
for (unsigned int layer=blendmapOffset; layer<numLayersInThisPass; ++layer)
|
|
||||||
{
|
|
||||||
std::string blendTextureName = mBlendmapList[getBlendmapIndexForLayer(layerOffset+layer)]->getName();
|
|
||||||
if (std::find(blendTextures.begin(), blendTextures.end(), blendTextureName) == blendTextures.end())
|
|
||||||
{
|
|
||||||
blendTextures.push_back(blendTextureName);
|
|
||||||
++numBlendTextures;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p->mShaderProperties.setProperty ("num_layers", sh::makeProperty (new sh::StringValue(Ogre::StringConverter::toString(numLayersInThisPass))));
|
p->mShaderProperties.setProperty ("num_layers", sh::makeProperty (new sh::StringValue(Ogre::StringConverter::toString(numLayersInThisPass))));
|
||||||
p->mShaderProperties.setProperty ("num_blendmaps", sh::makeProperty (new sh::StringValue(Ogre::StringConverter::toString(numBlendTextures))));
|
p->mShaderProperties.setProperty ("num_blendmaps", sh::makeProperty (new sh::StringValue(Ogre::StringConverter::toString(numBlendTextures))));
|
||||||
|
|
||||||
|
@ -250,7 +246,7 @@ namespace Terrain
|
||||||
blendmapStart = 0;
|
blendmapStart = 0;
|
||||||
else
|
else
|
||||||
blendmapStart = getBlendmapIndexForLayer(layerOffset+blendmapOffset);
|
blendmapStart = getBlendmapIndexForLayer(layerOffset+blendmapOffset);
|
||||||
for (Ogre::uint i = 0; i < numBlendTextures; ++i)
|
for (int i = 0; i < numBlendTextures; ++i)
|
||||||
{
|
{
|
||||||
sh::MaterialInstanceTextureUnit* blendTex = p->createTextureUnit ("blendMap" + Ogre::StringConverter::toString(i));
|
sh::MaterialInstanceTextureUnit* blendTex = p->createTextureUnit ("blendMap" + Ogre::StringConverter::toString(i));
|
||||||
blendTex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue(mBlendmapList[blendmapStart+i]->getName())));
|
blendTex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue(mBlendmapList[blendmapStart+i]->getName())));
|
||||||
|
@ -258,7 +254,7 @@ namespace Terrain
|
||||||
}
|
}
|
||||||
|
|
||||||
// layer maps
|
// layer maps
|
||||||
for (Ogre::uint i = 0; i < numLayersInThisPass; ++i)
|
for (int i = 0; i < numLayersInThisPass; ++i)
|
||||||
{
|
{
|
||||||
sh::MaterialInstanceTextureUnit* diffuseTex = p->createTextureUnit ("diffuseMap" + Ogre::StringConverter::toString(i));
|
sh::MaterialInstanceTextureUnit* diffuseTex = p->createTextureUnit ("diffuseMap" + Ogre::StringConverter::toString(i));
|
||||||
diffuseTex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue("textures\\"+mLayerList[layerOffset+i])));
|
diffuseTex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue("textures\\"+mLayerList[layerOffset+i])));
|
||||||
|
@ -280,7 +276,7 @@ namespace Terrain
|
||||||
}
|
}
|
||||||
|
|
||||||
// shadow
|
// shadow
|
||||||
if (mShadows)
|
if (shadows)
|
||||||
{
|
{
|
||||||
for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i)
|
for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i)
|
||||||
{
|
{
|
||||||
|
@ -292,7 +288,9 @@ namespace Terrain
|
||||||
Ogre::StringConverter::toString(numBlendTextures + numLayersInThisPass))));
|
Ogre::StringConverter::toString(numBlendTextures + numLayersInThisPass))));
|
||||||
|
|
||||||
// Make sure the pass index is fed to the permutation handler, because blendmap components may be different
|
// Make sure the pass index is fed to the permutation handler, because blendmap components may be different
|
||||||
p->mShaderProperties.setProperty ("pass_index", sh::makeProperty(new sh::IntValue(pass)));
|
p->mShaderProperties.setProperty ("pass_index", sh::makeProperty(new sh::IntValue(layerOffset)));
|
||||||
|
|
||||||
|
layerOffset += numLayersInThisPass;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,10 +43,6 @@ namespace Terrain
|
||||||
private:
|
private:
|
||||||
Ogre::MaterialPtr create (Ogre::MaterialPtr mat, bool renderCompositeMap, bool displayCompositeMap);
|
Ogre::MaterialPtr create (Ogre::MaterialPtr mat, bool renderCompositeMap, bool displayCompositeMap);
|
||||||
|
|
||||||
int getRequiredPasses ();
|
|
||||||
int getMaxLayersPerPass ();
|
|
||||||
|
|
||||||
int mNumLayers;
|
|
||||||
std::vector<std::string> mLayerList;
|
std::vector<std::string> mLayerList;
|
||||||
std::vector<Ogre::TexturePtr> mBlendmapList;
|
std::vector<Ogre::TexturePtr> mBlendmapList;
|
||||||
std::string mCompositeMap;
|
std::string mCompositeMap;
|
||||||
|
|
|
@ -151,8 +151,15 @@ QuadTreeNode::QuadTreeNode(Terrain* terrain, ChildDirection dir, float size, con
|
||||||
for (int i=0; i<4; ++i)
|
for (int i=0; i<4; ++i)
|
||||||
mNeighbours[i] = NULL;
|
mNeighbours[i] = NULL;
|
||||||
|
|
||||||
mSceneNode = mTerrain->getSceneManager()->getRootSceneNode()->createChildSceneNode(
|
if (mDirection == Root)
|
||||||
Ogre::Vector3(mCenter.x*8192, mCenter.y*8192, 0));
|
mSceneNode = mTerrain->getRootSceneNode();
|
||||||
|
else
|
||||||
|
mSceneNode = mTerrain->getSceneManager()->createSceneNode();
|
||||||
|
Ogre::Vector2 pos (0,0);
|
||||||
|
if (mParent)
|
||||||
|
pos = mParent->getCenter();
|
||||||
|
pos = mCenter - pos;
|
||||||
|
mSceneNode->setPosition(Ogre::Vector3(pos.x*8192, pos.y*8192, 0));
|
||||||
|
|
||||||
mLodLevel = log2(mSize);
|
mLodLevel = log2(mSize);
|
||||||
|
|
||||||
|
@ -221,13 +228,12 @@ void QuadTreeNode::update(const Ogre::Vector3 &cameraPos)
|
||||||
|
|
||||||
float dist = distance(mWorldBounds, cameraPos);
|
float dist = distance(mWorldBounds, cameraPos);
|
||||||
|
|
||||||
if (!mTerrain->getDistantLandEnabled())
|
bool distantLand = mTerrain->getDistantLandEnabled();
|
||||||
|
|
||||||
|
// Make sure our scene node is attached
|
||||||
|
if (!mSceneNode->isInSceneGraph())
|
||||||
{
|
{
|
||||||
if (dist > 8192*2)
|
mParent->getSceneNode()->addChild(mSceneNode);
|
||||||
{
|
|
||||||
destroyChunks();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \todo implement error metrics or some other means of not using arbitrary values
|
/// \todo implement error metrics or some other means of not using arbitrary values
|
||||||
|
@ -246,9 +252,22 @@ void QuadTreeNode::update(const Ogre::Vector3 &cameraPos)
|
||||||
if (dist > 8192*64)
|
if (dist > 8192*64)
|
||||||
wantedLod = 6;
|
wantedLod = 6;
|
||||||
|
|
||||||
|
bool hadChunk = hasChunk();
|
||||||
|
|
||||||
|
if (!distantLand && dist > 8192*2)
|
||||||
|
{
|
||||||
|
if (mIsActive)
|
||||||
|
{
|
||||||
|
destroyChunks(true);
|
||||||
|
mIsActive = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsActive = true;
|
||||||
|
|
||||||
if (mSize <= mTerrain->getMaxBatchSize() && mLodLevel <= wantedLod)
|
if (mSize <= mTerrain->getMaxBatchSize() && mLodLevel <= wantedLod)
|
||||||
{
|
{
|
||||||
bool hadChunk = hasChunk();
|
|
||||||
// Wanted LOD is small enough to render this node in one chunk
|
// Wanted LOD is small enough to render this node in one chunk
|
||||||
if (!mChunk)
|
if (!mChunk)
|
||||||
{
|
{
|
||||||
|
@ -297,32 +316,36 @@ void QuadTreeNode::update(const Ogre::Vector3 &cameraPos)
|
||||||
|
|
||||||
if (!hadChunk && hasChildren())
|
if (!hadChunk && hasChildren())
|
||||||
{
|
{
|
||||||
for (int i=0; i<4; ++i)
|
// Make sure child scene nodes are detached
|
||||||
mChildren[i]->hideChunks();
|
mSceneNode->removeAllChildren();
|
||||||
|
|
||||||
|
// If distant land is enabled, keep the chunks around in case we need them again,
|
||||||
|
// otherwise, prefer low memory usage
|
||||||
|
if (!distantLand)
|
||||||
|
for (int i=0; i<4; ++i)
|
||||||
|
mChildren[i]->destroyChunks(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Wanted LOD is too detailed to be rendered in one chunk,
|
// Wanted LOD is too detailed to be rendered in one chunk,
|
||||||
// so split it up by delegating to child nodes
|
// so split it up by delegating to child nodes
|
||||||
if (mChunk)
|
if (hadChunk)
|
||||||
mChunk->setVisible(false);
|
{
|
||||||
|
// If distant land is enabled, keep the chunks around in case we need them again,
|
||||||
|
// otherwise, prefer low memory usage
|
||||||
|
if (!distantLand)
|
||||||
|
destroyChunks(false);
|
||||||
|
else if (mChunk)
|
||||||
|
mChunk->setVisible(false);
|
||||||
|
}
|
||||||
assert(hasChildren() && "Leaf node's LOD needs to be 0");
|
assert(hasChildren() && "Leaf node's LOD needs to be 0");
|
||||||
for (int i=0; i<4; ++i)
|
for (int i=0; i<4; ++i)
|
||||||
mChildren[i]->update(cameraPos);
|
mChildren[i]->update(cameraPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuadTreeNode::hideChunks()
|
void QuadTreeNode::destroyChunks(bool children)
|
||||||
{
|
|
||||||
if (mChunk)
|
|
||||||
mChunk->setVisible(false);
|
|
||||||
else if (hasChildren())
|
|
||||||
for (int i=0; i<4; ++i)
|
|
||||||
mChildren[i]->hideChunks();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QuadTreeNode::destroyChunks()
|
|
||||||
{
|
{
|
||||||
if (mChunk)
|
if (mChunk)
|
||||||
{
|
{
|
||||||
|
@ -348,9 +371,9 @@ void QuadTreeNode::destroyChunks()
|
||||||
mCompositeMap.setNull();
|
mCompositeMap.setNull();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (hasChildren())
|
else if (children && hasChildren())
|
||||||
for (int i=0; i<4; ++i)
|
for (int i=0; i<4; ++i)
|
||||||
mChildren[i]->destroyChunks();
|
mChildren[i]->destroyChunks(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuadTreeNode::updateIndexBuffers()
|
void QuadTreeNode::updateIndexBuffers()
|
||||||
|
@ -366,7 +389,7 @@ void QuadTreeNode::updateIndexBuffers()
|
||||||
|
|
||||||
bool QuadTreeNode::hasChunk()
|
bool QuadTreeNode::hasChunk()
|
||||||
{
|
{
|
||||||
return mChunk && mChunk->getVisible();
|
return mSceneNode->isInSceneGraph() && mChunk && mChunk->getVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t QuadTreeNode::getActualLodLevel()
|
size_t QuadTreeNode::getActualLodLevel()
|
||||||
|
@ -400,7 +423,7 @@ void QuadTreeNode::prepareForCompositeMap(Ogre::TRect<float> area)
|
||||||
std::vector<std::string> layer;
|
std::vector<std::string> layer;
|
||||||
layer.push_back("_land_default.dds");
|
layer.push_back("_land_default.dds");
|
||||||
matGen.setLayerList(layer);
|
matGen.setLayerList(layer);
|
||||||
makeQuad(sceneMgr, area.left, area.top, area.right, area.bottom, matGen.generate(Ogre::MaterialPtr()));
|
makeQuad(sceneMgr, area.left, area.top, area.right, area.bottom, matGen.generateForCompositeMapRTT(Ogre::MaterialPtr()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mSize > 1)
|
if (mSize > 1)
|
||||||
|
|
|
@ -72,6 +72,8 @@ namespace Terrain
|
||||||
|
|
||||||
QuadTreeNode* getParent() { return mParent; }
|
QuadTreeNode* getParent() { return mParent; }
|
||||||
|
|
||||||
|
Ogre::SceneNode* getSceneNode() { return mSceneNode; }
|
||||||
|
|
||||||
int getSize() { return mSize; }
|
int getSize() { return mSize; }
|
||||||
Ogre::Vector2 getCenter() { return mCenter; }
|
Ogre::Vector2 getCenter() { return mCenter; }
|
||||||
|
|
||||||
|
@ -100,11 +102,8 @@ namespace Terrain
|
||||||
/// Call after QuadTreeNode::update!
|
/// Call after QuadTreeNode::update!
|
||||||
void updateIndexBuffers();
|
void updateIndexBuffers();
|
||||||
|
|
||||||
/// Hide chunks rendered by this node and all its children
|
/// Destroy chunks rendered by this node *and* its children (if param is true)
|
||||||
void hideChunks();
|
void destroyChunks(bool children);
|
||||||
|
|
||||||
/// Destroy chunks rendered by this node and all its children
|
|
||||||
void destroyChunks();
|
|
||||||
|
|
||||||
/// Get the effective LOD level if this node was rendered in one chunk
|
/// Get the effective LOD level if this node was rendered in one chunk
|
||||||
/// with ESM::Land::LAND_SIZE^2 vertices
|
/// with ESM::Land::LAND_SIZE^2 vertices
|
||||||
|
@ -127,6 +126,10 @@ namespace Terrain
|
||||||
// Stored here for convenience in case we need layer list again
|
// Stored here for convenience in case we need layer list again
|
||||||
MaterialGenerator* mMaterialGenerator;
|
MaterialGenerator* mMaterialGenerator;
|
||||||
|
|
||||||
|
/// Is this node (or any of its child nodes) currently configured to render itself?
|
||||||
|
/// (only relevant when distant land is disabled, otherwise whole terrain is always rendered)
|
||||||
|
bool mIsActive;
|
||||||
|
|
||||||
bool mIsDummy;
|
bool mIsDummy;
|
||||||
float mSize;
|
float mSize;
|
||||||
size_t mLodLevel; // LOD if we were to render this node in one chunk
|
size_t mLodLevel; // LOD if we were to render this node in one chunk
|
||||||
|
|
|
@ -59,6 +59,7 @@ namespace Terrain
|
||||||
, mVisibilityFlags(visibilityFlags)
|
, mVisibilityFlags(visibilityFlags)
|
||||||
, mDistantLand(distantLand)
|
, mDistantLand(distantLand)
|
||||||
, mShaders(shaders)
|
, mShaders(shaders)
|
||||||
|
, mVisible(true)
|
||||||
{
|
{
|
||||||
mCompositeMapSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC);
|
mCompositeMapSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC);
|
||||||
|
|
||||||
|
@ -81,6 +82,8 @@ namespace Terrain
|
||||||
// Adjust the center according to the new size
|
// Adjust the center according to the new size
|
||||||
Ogre::Vector3 center = mBounds.getCenter() + Ogre::Vector3((size-origSizeX)/2.f, (size-origSizeY)/2.f, 0);
|
Ogre::Vector3 center = mBounds.getCenter() + Ogre::Vector3((size-origSizeX)/2.f, (size-origSizeY)/2.f, 0);
|
||||||
|
|
||||||
|
mRootSceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
|
||||||
|
|
||||||
mRootNode = new QuadTreeNode(this, Root, size, Ogre::Vector2(center.x, center.y), NULL);
|
mRootNode = new QuadTreeNode(this, Root, size, Ogre::Vector2(center.x, center.y), NULL);
|
||||||
buildQuadTree(mRootNode);
|
buildQuadTree(mRootNode);
|
||||||
mRootNode->initAabb();
|
mRootNode->initAabb();
|
||||||
|
@ -142,6 +145,8 @@ namespace Terrain
|
||||||
|
|
||||||
void Terrain::update(const Ogre::Vector3& cameraPos)
|
void Terrain::update(const Ogre::Vector3& cameraPos)
|
||||||
{
|
{
|
||||||
|
if (!mVisible)
|
||||||
|
return;
|
||||||
mRootNode->update(cameraPos);
|
mRootNode->update(cameraPos);
|
||||||
mRootNode->updateIndexBuffers();
|
mRootNode->updateIndexBuffers();
|
||||||
}
|
}
|
||||||
|
@ -379,8 +384,12 @@ namespace Terrain
|
||||||
|
|
||||||
void Terrain::setVisible(bool visible)
|
void Terrain::setVisible(bool visible)
|
||||||
{
|
{
|
||||||
|
if (visible && !mVisible)
|
||||||
|
mSceneMgr->getRootSceneNode()->addChild(mRootSceneNode);
|
||||||
|
else if (!visible && mVisible)
|
||||||
|
mSceneMgr->getRootSceneNode()->removeChild(mRootSceneNode);
|
||||||
|
|
||||||
mVisible = visible;
|
mVisible = visible;
|
||||||
mRootNode->setVisible(visible);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Terrain::getVisible()
|
bool Terrain::getVisible()
|
||||||
|
|
|
@ -55,6 +55,8 @@ namespace Terrain
|
||||||
|
|
||||||
Ogre::SceneManager* getSceneManager() { return mSceneMgr; }
|
Ogre::SceneManager* getSceneManager() { return mSceneMgr; }
|
||||||
|
|
||||||
|
Ogre::SceneNode* getRootSceneNode() { return mRootSceneNode; }
|
||||||
|
|
||||||
Storage* getStorage() { return mStorage; }
|
Storage* getStorage() { return mStorage; }
|
||||||
|
|
||||||
/// Show or hide the whole terrain
|
/// Show or hide the whole terrain
|
||||||
|
@ -83,6 +85,7 @@ namespace Terrain
|
||||||
bool mVisible;
|
bool mVisible;
|
||||||
|
|
||||||
QuadTreeNode* mRootNode;
|
QuadTreeNode* mRootNode;
|
||||||
|
Ogre::SceneNode* mRootSceneNode;
|
||||||
Storage* mStorage;
|
Storage* mStorage;
|
||||||
|
|
||||||
int mVisibilityFlags;
|
int mVisibilityFlags;
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
#if LIGHTING
|
#if LIGHTING
|
||||||
@shAllocatePassthrough(3, lightResult)
|
@shAllocatePassthrough(3, lightResult)
|
||||||
@shAllocatePassthrough(3, directionalResult)
|
@shAllocatePassthrough(3, directionalResult)
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SHADOWS
|
#if SHADOWS
|
||||||
@shAllocatePassthrough(4, lightSpacePos0)
|
@shAllocatePassthrough(4, lightSpacePos0)
|
||||||
|
@ -49,6 +48,7 @@
|
||||||
@shAllocatePassthrough(4, lightSpacePos@shIterator)
|
@shAllocatePassthrough(4, lightSpacePos@shIterator)
|
||||||
@shEndForeach
|
@shEndForeach
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SH_VERTEX_SHADER
|
#ifdef SH_VERTEX_SHADER
|
||||||
|
|
||||||
|
@ -200,6 +200,7 @@
|
||||||
|
|
||||||
@shPassthroughFragmentInputs
|
@shPassthroughFragmentInputs
|
||||||
|
|
||||||
|
#if LIGHTING
|
||||||
#if SHADOWS
|
#if SHADOWS
|
||||||
shSampler2D(shadowMap0)
|
shSampler2D(shadowMap0)
|
||||||
shUniform(float2, invShadowmapSize0) @shAutoConstant(invShadowmapSize0, inverse_texture_size, @shPropertyString(shadowtexture_offset))
|
shUniform(float2, invShadowmapSize0) @shAutoConstant(invShadowmapSize0, inverse_texture_size, @shPropertyString(shadowtexture_offset))
|
||||||
|
@ -215,6 +216,7 @@
|
||||||
#if SHADOWS || SHADOWS_PSSM
|
#if SHADOWS || SHADOWS_PSSM
|
||||||
shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart)
|
shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart)
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (UNDERWATER) || (FOG)
|
#if (UNDERWATER) || (FOG)
|
||||||
shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix)
|
shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix)
|
||||||
|
|
Loading…
Reference in a new issue