mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-05-10 20:46:55 +03:00
Merge branch 'master' of https://github.com/zinnschlag/openmw into tgm
This commit is contained in:
commit
f65172bdca
123 changed files with 1494 additions and 1203 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
35
components/loadinglistener/loadinglistener.hpp
Normal file
35
components/loadinglistener/loadinglistener.hpp
Normal 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
|
|
@ -4,7 +4,7 @@
|
|||
#include <OgreHardwareBufferManager.h>
|
||||
|
||||
#include "quadtreenode.hpp"
|
||||
#include "terrain.hpp"
|
||||
#include "world.hpp"
|
||||
#include "storage.hpp"
|
||||
|
||||
namespace Terrain
|
||||
|
|
|
@ -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 ¢er, QuadTreeNode* parent)
|
||||
QuadTreeNode::QuadTreeNode(World* terrain, ChildDirection dir, float size, const Ogre::Vector2 ¢er, 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
Loading…
Add table
Add a link
Reference in a new issue