Merge branch 'master' of https://github.com/zinnschlag/openmw into tgm

This commit is contained in:
mckibbenta 2013-08-29 20:26:36 -04:00
commit f65172bdca
123 changed files with 1494 additions and 1203 deletions

View file

@ -67,7 +67,11 @@ add_component_dir (translation
)
add_component_dir (terrain
quadtreenode chunk terrain storage material
quadtreenode chunk world storage material
)
add_component_dir (loadinglistener
loadinglistener
)
find_package(Qt4 COMPONENTS QtCore QtGui)

View file

@ -70,6 +70,11 @@ public:
void openRaw(const std::string &file);
/// Get the file size. Make sure that the file has been opened!
size_t getFileSize() { return mEsm->size(); }
/// Get the current position in the file. Make sure that the file has been opened!
size_t getFileOffset() { return mEsm->tell(); }
// This is a quick hack for multiple esm/esp files. Each plugin introduces its own
// terrain palette, but ESMReader does not pass a reference to the correct plugin
// to the individual load() methods. This hack allows to pass this reference

View file

@ -0,0 +1,35 @@
#ifndef COMPONENTS_LOADINGLISTENER_H
#define COMPONENTS_LOADINGLISTENER_H
namespace Loading
{
class Listener
{
public:
virtual void setLabel (const std::string& label) = 0;
// Use ScopedLoad instead of using these directly
virtual void loadingOn() = 0;
virtual void loadingOff() = 0;
/// Indicate that some progress has been made, without specifying how much
virtual void indicateProgress () = 0;
virtual void setProgressRange (size_t range) = 0;
virtual void setProgress (size_t value) = 0;
virtual void increaseProgress (size_t increase) = 0;
/// Indicate the scene is now ready to be shown
virtual void removeWallpaper() = 0;
};
// Used for stopping a loading sequence when the object goes out of scope
struct ScopedLoad
{
ScopedLoad(Listener* l) : mListener(l) { mListener->loadingOn(); }
~ScopedLoad() { mListener->loadingOff(); }
Listener* mListener;
};
}
#endif

View file

@ -4,7 +4,7 @@
#include <OgreHardwareBufferManager.h>
#include "quadtreenode.hpp"
#include "terrain.hpp"
#include "world.hpp"
#include "storage.hpp"
namespace Terrain

View file

@ -3,7 +3,7 @@
#include <OgreSceneManager.h>
#include <OgreManualObject.h>
#include "terrain.hpp"
#include "world.hpp"
#include "chunk.hpp"
#include "storage.hpp"
@ -13,6 +13,13 @@ using namespace Terrain;
namespace
{
int Log2( int n )
{
assert(n > 0);
int targetlevel = 0;
while (n >>= 1) ++targetlevel;
return targetlevel;
}
// Utility functions for neighbour finding algorithm
ChildDirection reflect(ChildDirection dir, Direction dir2)
@ -132,7 +139,7 @@ namespace
}
}
QuadTreeNode::QuadTreeNode(Terrain* terrain, ChildDirection dir, float size, const Ogre::Vector2 &center, QuadTreeNode* parent)
QuadTreeNode::QuadTreeNode(World* terrain, ChildDirection dir, float size, const Ogre::Vector2 &center, QuadTreeNode* parent)
: mSize(size)
, mCenter(center)
, mParent(parent)
@ -161,7 +168,7 @@ QuadTreeNode::QuadTreeNode(Terrain* terrain, ChildDirection dir, float size, con
pos = mCenter - pos;
mSceneNode->setPosition(Ogre::Vector3(pos.x*8192, pos.y*8192, 0));
mLodLevel = log2(mSize);
mLodLevel = Log2(mSize);
mMaterialGenerator = new MaterialGenerator(mTerrain->getShadersEnabled());
}
@ -220,7 +227,7 @@ const Ogre::AxisAlignedBox& QuadTreeNode::getBoundingBox()
return mBounds;
}
void QuadTreeNode::update(const Ogre::Vector3 &cameraPos)
void QuadTreeNode::update(const Ogre::Vector3 &cameraPos, Loading::Listener* loadingListener)
{
const Ogre::AxisAlignedBox& bounds = getBoundingBox();
if (bounds.isNull())
@ -254,6 +261,9 @@ void QuadTreeNode::update(const Ogre::Vector3 &cameraPos)
bool hadChunk = hasChunk();
if (loadingListener)
loadingListener->indicateProgress();
if (!distantLand && dist > 8192*2)
{
if (mIsActive)
@ -341,7 +351,7 @@ void QuadTreeNode::update(const Ogre::Vector3 &cameraPos)
}
assert(hasChildren() && "Leaf node's LOD needs to be 0");
for (int i=0; i<4; ++i)
mChildren[i]->update(cameraPos);
mChildren[i]->update(cameraPos, loadingListener);
}
}

View file

@ -5,6 +5,8 @@
#include <OgreVector2.h>
#include <OgreTexture.h>
#include <components/loadinglistener/loadinglistener.hpp>
namespace Ogre
{
class Rectangle2D;
@ -12,7 +14,7 @@ namespace Ogre
namespace Terrain
{
class Terrain;
class World;
class Chunk;
class MaterialGenerator;
@ -46,7 +48,7 @@ namespace Terrain
/// @param size size (in *cell* units!)
/// @param center center (in *cell* units!)
/// @param parent parent node
QuadTreeNode (Terrain* terrain, ChildDirection dir, float size, const Ogre::Vector2& center, QuadTreeNode* parent);
QuadTreeNode (World* terrain, ChildDirection dir, float size, const Ogre::Vector2& center, QuadTreeNode* parent);
~QuadTreeNode();
void setVisible(bool visible);
@ -93,10 +95,10 @@ namespace Terrain
/// Get bounding box in local coordinates
const Ogre::AxisAlignedBox& getBoundingBox();
Terrain* getTerrain() { return mTerrain; }
World* getTerrain() { return mTerrain; }
/// Adjust LODs for the given camera position, possibly splitting up chunks or merging them.
void update (const Ogre::Vector3& cameraPos);
void update (const Ogre::Vector3& cameraPos, Loading::Listener* loadingListener);
/// Adjust index buffers of chunks to stitch together chunks of different LOD, so that cracks are avoided.
/// Call after QuadTreeNode::update!
@ -146,7 +148,7 @@ namespace Terrain
Chunk* mChunk;
Terrain* mTerrain;
World* mTerrain;
Ogre::TexturePtr mCompositeMap;

View file

@ -1,4 +1,4 @@
#include "terrain.hpp"
#include "world.hpp"
#include <OgreAxisAlignedBox.h>
#include <OgreCamera.h>
@ -7,6 +7,7 @@
#include <OgreRoot.h>
#include <components/esm/loadland.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
#include "storage.hpp"
#include "quadtreenode.hpp"
@ -51,7 +52,8 @@ namespace
namespace Terrain
{
Terrain::Terrain(Ogre::SceneManager* sceneMgr, Storage* storage, int visibilityFlags, bool distantLand, bool shaders)
World::World(Loading::Listener* loadingListener, Ogre::SceneManager* sceneMgr,
Storage* storage, int visibilityFlags, bool distantLand, bool shaders)
: mStorage(storage)
, mMinBatchSize(1)
, mMaxBatchSize(64)
@ -60,7 +62,11 @@ namespace Terrain
, mDistantLand(distantLand)
, mShaders(shaders)
, mVisible(true)
, mLoadingListener(loadingListener)
{
loadingListener->setLabel("Creating terrain");
loadingListener->indicateProgress();
mCompositeMapSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC);
Ogre::Camera* compositeMapCam = mCompositeMapSceneMgr->createCamera("a");
@ -86,17 +92,20 @@ namespace Terrain
mRootNode = new QuadTreeNode(this, Root, size, Ogre::Vector2(center.x, center.y), NULL);
buildQuadTree(mRootNode);
loadingListener->indicateProgress();
mRootNode->initAabb();
loadingListener->indicateProgress();
mRootNode->initNeighbours();
loadingListener->indicateProgress();
}
Terrain::~Terrain()
World::~World()
{
delete mRootNode;
delete mStorage;
}
void Terrain::buildQuadTree(QuadTreeNode *node)
void World::buildQuadTree(QuadTreeNode *node)
{
float halfSize = node->getSize()/2.f;
@ -143,15 +152,15 @@ namespace Terrain
node->markAsDummy();
}
void Terrain::update(const Ogre::Vector3& cameraPos)
void World::update(const Ogre::Vector3& cameraPos)
{
if (!mVisible)
return;
mRootNode->update(cameraPos);
mRootNode->update(cameraPos, mLoadingListener);
mRootNode->updateIndexBuffers();
}
Ogre::AxisAlignedBox Terrain::getWorldBoundingBox (const Ogre::Vector2& center)
Ogre::AxisAlignedBox World::getWorldBoundingBox (const Ogre::Vector2& center)
{
if (center.x > mBounds.getMaximum().x
|| center.x < mBounds.getMinimum().x
@ -165,7 +174,7 @@ namespace Terrain
return box;
}
Ogre::HardwareVertexBufferSharedPtr Terrain::getVertexBuffer(int numVertsOneSide)
Ogre::HardwareVertexBufferSharedPtr World::getVertexBuffer(int numVertsOneSide)
{
if (mUvBufferMap.find(numVertsOneSide) != mUvBufferMap.end())
{
@ -197,7 +206,7 @@ namespace Terrain
return buffer;
}
Ogre::HardwareIndexBufferSharedPtr Terrain::getIndexBuffer(int flags, size_t& numIndices)
Ogre::HardwareIndexBufferSharedPtr World::getIndexBuffer(int flags, size_t& numIndices)
{
if (mIndexBufferMap.find(flags) != mIndexBufferMap.end())
{
@ -358,31 +367,31 @@ namespace Terrain
return buffer;
}
void Terrain::renderCompositeMap(Ogre::TexturePtr target)
void World::renderCompositeMap(Ogre::TexturePtr target)
{
mCompositeMapRenderTarget->update();
target->getBuffer()->blit(mCompositeMapRenderTexture->getBuffer());
}
void Terrain::clearCompositeMapSceneManager()
void World::clearCompositeMapSceneManager()
{
mCompositeMapSceneMgr->destroyAllManualObjects();
mCompositeMapSceneMgr->clearScene();
}
float Terrain::getHeightAt(const Ogre::Vector3 &worldPos)
float World::getHeightAt(const Ogre::Vector3 &worldPos)
{
return mStorage->getHeightAt(worldPos);
}
void Terrain::applyMaterials(bool shadows, bool splitShadows)
void World::applyMaterials(bool shadows, bool splitShadows)
{
mShadows = shadows;
mSplitShadows = splitShadows;
mRootNode->applyMaterials();
}
void Terrain::setVisible(bool visible)
void World::setVisible(bool visible)
{
if (visible && !mVisible)
mSceneMgr->getRootSceneNode()->addChild(mRootSceneNode);
@ -392,7 +401,7 @@ namespace Terrain
mVisible = visible;
}
bool Terrain::getVisible()
bool World::getVisible()
{
return mVisible;
}

View file

@ -6,6 +6,11 @@
#include <OgreAxisAlignedBox.h>
#include <OgreTexture.h>
namespace Loading
{
class Listener;
}
namespace Ogre
{
class Camera;
@ -24,10 +29,11 @@ namespace Terrain
* Cracks at LOD transitions are avoided using stitching.
* @note Multiple cameras are not supported yet
*/
class Terrain
class World
{
public:
/// @note takes ownership of \a storage
/// @param loadingListener Listener to update with progress
/// @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
@ -35,8 +41,11 @@ namespace Terrain
/// This is a temporary option until it can be streamlined.
/// @param shaders Whether to use splatting shader, or multi-pass fixed function splatting. Shader is usually
/// faster so this is just here for compatibility.
Terrain(Ogre::SceneManager* sceneMgr, Storage* storage, int visiblityFlags, bool distantLand, bool shaders);
~Terrain();
World(Loading::Listener* loadingListener, Ogre::SceneManager* sceneMgr,
Storage* storage, int visiblityFlags, bool distantLand, bool shaders);
~World();
void setLoadingListener(Loading::Listener* loadingListener) { mLoadingListener = loadingListener; }
bool getDistantLandEnabled() { return mDistantLand; }
bool getShadersEnabled() { return mShaders; }
@ -84,6 +93,8 @@ namespace Terrain
bool mSplitShadows;
bool mVisible;
Loading::Listener* mLoadingListener;
QuadTreeNode* mRootNode;
Ogre::SceneNode* mRootSceneNode;
Storage* mStorage;