mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-05-02 23:08:00 +03:00
Move terrain grid implementation to a component so the editor can use it (Feature #1597)
This commit is contained in:
parent
982453d4f6
commit
8c26f802e6
5 changed files with 14 additions and 19 deletions
|
@ -23,7 +23,7 @@ add_openmw_dir (mwrender
|
|||
renderingmanager debugging sky camera animation npcanimation creatureanimation activatoranimation
|
||||
actors objects renderinginterface localmap occlusionquery water shadows
|
||||
characterpreview globalmap videoplayer ripplesimulation refraction
|
||||
terrainstorage renderconst effectmanager weaponanimation terraingrid
|
||||
terrainstorage renderconst effectmanager weaponanimation
|
||||
)
|
||||
|
||||
add_openmw_dir (mwinput
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/terrain/defaultworld.hpp>
|
||||
#include <components/terrain/terraingrid.hpp>
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
|
@ -45,7 +46,6 @@
|
|||
#include "globalmap.hpp"
|
||||
#include "terrainstorage.hpp"
|
||||
#include "effectmanager.hpp"
|
||||
#include "terraingrid.hpp"
|
||||
|
||||
using namespace MWRender;
|
||||
using namespace Ogre;
|
||||
|
@ -1045,7 +1045,7 @@ void RenderingManager::enableTerrain(bool enable)
|
|||
mTerrain = new Terrain::DefaultWorld(mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain,
|
||||
Settings::Manager::getBool("shader", "Terrain"), Terrain::Align_XY, 1, 64);
|
||||
else
|
||||
mTerrain = new MWRender::TerrainGrid(mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain,
|
||||
mTerrain = new Terrain::TerrainGrid(mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain,
|
||||
Settings::Manager::getBool("shader", "Terrain"), Terrain::Align_XY);
|
||||
mTerrain->applyMaterials(Settings::Manager::getBool("enabled", "Shadows"),
|
||||
Settings::Manager::getBool("split", "Shadows"));
|
||||
|
|
|
@ -1,167 +0,0 @@
|
|||
#include "terraingrid.hpp"
|
||||
|
||||
#include <OgreSceneManager.h>
|
||||
#include <OgreSceneNode.h>
|
||||
#include <OgreAxisAlignedBox.h>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
||||
#include <components/terrain/chunk.hpp>
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
|
||||
TerrainGrid::TerrainGrid(Ogre::SceneManager *sceneMgr, Terrain::Storage *storage, int visibilityFlags, bool shaders, Terrain::Alignment align)
|
||||
: Terrain::World(sceneMgr, storage, visibilityFlags, shaders, align)
|
||||
, mVisible(true)
|
||||
{
|
||||
mRootNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
|
||||
}
|
||||
|
||||
TerrainGrid::~TerrainGrid()
|
||||
{
|
||||
while (!mGrid.empty())
|
||||
{
|
||||
unloadCell(mGrid.begin()->first.first, mGrid.begin()->first.second);
|
||||
}
|
||||
|
||||
mSceneMgr->destroySceneNode(mRootNode);
|
||||
}
|
||||
|
||||
void TerrainGrid::update(const Ogre::Vector3 &cameraPos)
|
||||
{
|
||||
}
|
||||
|
||||
void TerrainGrid::loadCell(int x, int y)
|
||||
{
|
||||
if (mGrid.find(std::make_pair(x, y)) != mGrid.end())
|
||||
return; // already loaded
|
||||
|
||||
Ogre::Vector2 center(x+0.5, y+0.5);
|
||||
float minH, maxH;
|
||||
if (!mStorage->getMinMaxHeights(1, center, minH, maxH))
|
||||
return; // no terrain defined
|
||||
|
||||
Ogre::Vector3 min (-0.5*mStorage->getCellWorldSize(),
|
||||
-0.5*mStorage->getCellWorldSize(),
|
||||
minH);
|
||||
Ogre::Vector3 max (0.5*mStorage->getCellWorldSize(),
|
||||
0.5*mStorage->getCellWorldSize(),
|
||||
maxH);
|
||||
|
||||
Ogre::AxisAlignedBox bounds(min, max);
|
||||
|
||||
GridElement element;
|
||||
|
||||
Ogre::Vector2 worldCenter = center*mStorage->getCellWorldSize();
|
||||
element.mSceneNode = mRootNode->createChildSceneNode(Ogre::Vector3(worldCenter.x, worldCenter.y, 0));
|
||||
|
||||
std::vector<float> positions;
|
||||
std::vector<float> normals;
|
||||
std::vector<Ogre::uint8> colours;
|
||||
mStorage->fillVertexBuffers(0, 1, center, mAlign, positions, normals, colours);
|
||||
|
||||
element.mChunk = new Terrain::Chunk(mCache.getUVBuffer(), bounds, positions, normals, colours);
|
||||
element.mChunk->setIndexBuffer(mCache.getIndexBuffer(0));
|
||||
element.mChunk->setVisibilityFlags(mVisibilityFlags);
|
||||
element.mChunk->setCastShadows(true);
|
||||
|
||||
std::vector<Ogre::PixelBox> blendmaps;
|
||||
std::vector<Terrain::LayerInfo> layerList;
|
||||
mStorage->getBlendmaps(1, center, mShaders, blendmaps, layerList);
|
||||
|
||||
element.mMaterialGenerator.setLayerList(layerList);
|
||||
|
||||
// upload blendmaps to GPU
|
||||
std::vector<Ogre::TexturePtr> blendTextures;
|
||||
for (std::vector<Ogre::PixelBox>::const_iterator it = blendmaps.begin(); it != blendmaps.end(); ++it)
|
||||
{
|
||||
static int count=0;
|
||||
Ogre::TexturePtr map = Ogre::TextureManager::getSingleton().createManual("terrain/blend/"
|
||||
+ Ogre::StringConverter::toString(count++), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
Ogre::TEX_TYPE_2D, it->getWidth(), it->getHeight(), 0, it->format);
|
||||
|
||||
Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(it->data, it->getWidth()*it->getHeight()*Ogre::PixelUtil::getNumElemBytes(it->format), true));
|
||||
map->loadRawData(stream, it->getWidth(), it->getHeight(), it->format);
|
||||
blendTextures.push_back(map);
|
||||
}
|
||||
|
||||
element.mMaterialGenerator.setBlendmapList(blendTextures);
|
||||
|
||||
element.mSceneNode->attachObject(element.mChunk);
|
||||
updateMaterial(element);
|
||||
|
||||
mGrid[std::make_pair(x,y)] = element;
|
||||
}
|
||||
|
||||
void TerrainGrid::updateMaterial(GridElement &element)
|
||||
{
|
||||
element.mMaterialGenerator.enableShadows(getShadowsEnabled());
|
||||
element.mMaterialGenerator.enableSplitShadows(getSplitShadowsEnabled());
|
||||
element.mChunk->setMaterial(element.mMaterialGenerator.generate());
|
||||
}
|
||||
|
||||
void TerrainGrid::unloadCell(int x, int y)
|
||||
{
|
||||
Grid::iterator it = mGrid.find(std::make_pair(x,y));
|
||||
if (it == mGrid.end())
|
||||
return;
|
||||
|
||||
GridElement& element = it->second;
|
||||
delete element.mChunk;
|
||||
element.mChunk = NULL;
|
||||
|
||||
const std::vector<Ogre::TexturePtr>& blendmaps = element.mMaterialGenerator.getBlendmapList();
|
||||
for (std::vector<Ogre::TexturePtr>::const_iterator it = blendmaps.begin(); it != blendmaps.end(); ++it)
|
||||
Ogre::TextureManager::getSingleton().remove((*it)->getName());
|
||||
|
||||
mSceneMgr->destroySceneNode(element.mSceneNode);
|
||||
element.mSceneNode = NULL;
|
||||
|
||||
mGrid.erase(it);
|
||||
}
|
||||
|
||||
void TerrainGrid::applyMaterials(bool shadows, bool splitShadows)
|
||||
{
|
||||
mShadows = shadows;
|
||||
mSplitShadows = splitShadows;
|
||||
for (Grid::iterator it = mGrid.begin(); it != mGrid.end(); ++it)
|
||||
{
|
||||
updateMaterial(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
bool TerrainGrid::getVisible()
|
||||
{
|
||||
return mVisible;
|
||||
}
|
||||
|
||||
void TerrainGrid::setVisible(bool visible)
|
||||
{
|
||||
mVisible = visible;
|
||||
mRootNode->setVisible(visible);
|
||||
}
|
||||
|
||||
Ogre::AxisAlignedBox TerrainGrid::getWorldBoundingBox (const Ogre::Vector2& center)
|
||||
{
|
||||
int cellX, cellY;
|
||||
MWBase::Environment::get().getWorld()->positionToIndex(center.x, center.y, cellX, cellY);
|
||||
|
||||
Grid::iterator it = mGrid.find(std::make_pair(cellX, cellY));
|
||||
if (it == mGrid.end())
|
||||
return Ogre::AxisAlignedBox::BOX_NULL;
|
||||
|
||||
Terrain::Chunk* chunk = it->second.mChunk;
|
||||
Ogre::SceneNode* node = it->second.mSceneNode;
|
||||
Ogre::AxisAlignedBox box = chunk->getBoundingBox();
|
||||
box = Ogre::AxisAlignedBox(box.getMinimum() + node->getPosition(), box.getMaximum() + node->getPosition());
|
||||
return box;
|
||||
}
|
||||
|
||||
void TerrainGrid::syncLoad()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
#ifndef OPENMW_MWRENDER_TERRAINGRID_H
|
||||
#define OPENMW_MWRENDER_TERRAINGRID_H
|
||||
|
||||
#include <components/terrain/world.hpp>
|
||||
#include <components/terrain/material.hpp>
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
class Chunk;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
|
||||
struct GridElement
|
||||
{
|
||||
Ogre::SceneNode* mSceneNode;
|
||||
|
||||
Terrain::MaterialGenerator mMaterialGenerator;
|
||||
|
||||
Terrain::Chunk* mChunk;
|
||||
};
|
||||
|
||||
/// @brief Simple terrain implementation that loads cells in a grid, with no LOD
|
||||
class TerrainGrid : public Terrain::World
|
||||
{
|
||||
public:
|
||||
/// @note takes ownership of \a storage
|
||||
/// @param sceneMgr scene manager to use
|
||||
/// @param storage Storage instance to get terrain data from (heights, normals, colors, textures..)
|
||||
/// @param visbilityFlags visibility flags for the created meshes
|
||||
/// @param shaders Whether to use splatting shader, or multi-pass fixed function splatting. Shader is usually
|
||||
/// faster so this is just here for compatibility.
|
||||
/// @param align The align of the terrain, see Alignment enum
|
||||
TerrainGrid(Ogre::SceneManager* sceneMgr,
|
||||
Terrain::Storage* storage, int visibilityFlags, bool shaders, Terrain::Alignment align);
|
||||
~TerrainGrid();
|
||||
|
||||
/// Update chunk LODs according to this camera position
|
||||
virtual void update (const Ogre::Vector3& cameraPos);
|
||||
|
||||
virtual void loadCell(int x, int y);
|
||||
virtual void unloadCell(int x, int y);
|
||||
|
||||
/// Get the world bounding box of a chunk of terrain centered at \a center
|
||||
virtual Ogre::AxisAlignedBox getWorldBoundingBox (const Ogre::Vector2& center);
|
||||
|
||||
/// Show or hide the whole terrain
|
||||
/// @note this setting may be invalidated once you call Terrain::update, so do not call it while the terrain should be hidden
|
||||
virtual void setVisible(bool visible);
|
||||
virtual bool getVisible();
|
||||
|
||||
/// Recreate materials used by terrain chunks. This should be called whenever settings of
|
||||
/// the material factory are changed. (Relying on the factory to update those materials is not
|
||||
/// enough, since turning a feature on/off can change the number of texture units available for layer/blend
|
||||
/// textures, and to properly respond to this we may need to change the structure of the material, such as
|
||||
/// adding or removing passes. This can only be achieved by a full rebuild.)
|
||||
virtual void applyMaterials(bool shadows, bool splitShadows);
|
||||
|
||||
/// Wait until all background loading is complete.
|
||||
virtual void syncLoad();
|
||||
|
||||
private:
|
||||
void updateMaterial (GridElement& element);
|
||||
|
||||
typedef std::map<std::pair<int, int>, GridElement> Grid;
|
||||
Grid mGrid;
|
||||
|
||||
Ogre::SceneNode* mRootNode;
|
||||
bool mVisible;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue