forked from teamnwah/openmw-tes3coop
cell render refactoring
This commit is contained in:
parent
7c8b3ea1a9
commit
47790e6feb
6 changed files with 274 additions and 162 deletions
|
@ -36,8 +36,9 @@ set(GAME_HEADER game/mwinput/inputmanager.hpp)
|
||||||
set(ESM_STORE esm_store/store.cpp esm_store/cell_store.cpp)
|
set(ESM_STORE esm_store/store.cpp esm_store/cell_store.cpp)
|
||||||
set(ESM_STORE_HEADER esm_store/cell_store.hpp esm_store/reclists.hpp esm_store/store.hpp)
|
set(ESM_STORE_HEADER esm_store/cell_store.hpp esm_store/reclists.hpp esm_store/store.hpp)
|
||||||
|
|
||||||
set(GAMEREND game/mwrender/mwscene.cpp game/mwrender/cell.cpp)
|
set(GAMEREND game/mwrender/mwscene.cpp game/mwrender/cell.cpp game/mwrender/interior.cpp)
|
||||||
set(GAMEREND_HEADER game/mwrender/cell.hpp game/mwrender/mwscene.hpp)
|
set(GAMEREND_HEADER game/mwrender/cell.hpp game/mwrender/mwscene.hpp
|
||||||
|
game/mwrender/interior.hpp)
|
||||||
|
|
||||||
set(ESM_HEADER esm/defs.hpp esm/loadcell.hpp esm/loadfact.hpp esm/loadltex.hpp
|
set(ESM_HEADER esm/defs.hpp esm/loadcell.hpp esm/loadfact.hpp esm/loadltex.hpp
|
||||||
esm/loadskil.hpp
|
esm/loadskil.hpp
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "ogre/renderer.hpp"
|
#include "ogre/renderer.hpp"
|
||||||
#include "tools/fileops.hpp"
|
#include "tools/fileops.hpp"
|
||||||
|
|
||||||
#include "mwrender/cell.hpp"
|
#include "mwrender/interior.hpp"
|
||||||
#include "mwrender/mwscene.hpp"
|
#include "mwrender/mwscene.hpp"
|
||||||
#include "mwinput/inputmanager.hpp"
|
#include "mwinput/inputmanager.hpp"
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ void maintest (std::string dataDir, const std::string& cellName)
|
||||||
MWRender::MWScene scene(ogre);
|
MWRender::MWScene scene(ogre);
|
||||||
|
|
||||||
// This connects the cell data with the rendering scene.
|
// This connects the cell data with the rendering scene.
|
||||||
MWRender::CellRender rend(cell, scene);
|
MWRender::InteriorCellRender rend(cell, scene);
|
||||||
|
|
||||||
// Load the cell and insert it into the renderer
|
// Load the cell and insert it into the renderer
|
||||||
rend.show();
|
rend.show();
|
||||||
|
|
|
@ -1,122 +1,42 @@
|
||||||
#include "cell.hpp"
|
#include "cell.hpp"
|
||||||
|
|
||||||
#include <OgreEntity.h>
|
|
||||||
|
|
||||||
#include "nifogre/ogre_nif_loader.hpp"
|
|
||||||
|
|
||||||
using namespace MWRender;
|
using namespace MWRender;
|
||||||
using namespace Ogre;
|
|
||||||
using namespace ESMS;
|
|
||||||
|
|
||||||
// Inserts one mesh into the scene
|
void CellRender::insertCell(const ESMS::CellStore &cell)
|
||||||
void CellRender::insertMesh(const std::string &mesh, // NIF file
|
|
||||||
const CellRef &ref) // Reference information
|
|
||||||
{
|
{
|
||||||
// Create and place scene node for this object
|
|
||||||
SceneNode *node = base->createChildSceneNode();
|
|
||||||
|
|
||||||
const float *f = ref.pos.pos;
|
|
||||||
node->setPosition(f[0], f[1], f[2]);
|
|
||||||
node->setScale(ref.scale, ref.scale, ref.scale);
|
|
||||||
|
|
||||||
// Convert MW rotation to a quaternion:
|
|
||||||
f = ref.pos.rot;
|
|
||||||
|
|
||||||
// Rotate around X axis
|
|
||||||
Quaternion xr(Radian(-f[0]), Vector3::UNIT_X);
|
|
||||||
|
|
||||||
// Rotate around Y axis
|
|
||||||
Quaternion yr(Radian(-f[1]), Vector3::UNIT_Y);
|
|
||||||
|
|
||||||
// Rotate around Z axis
|
|
||||||
Quaternion zr(Radian(-f[2]), Vector3::UNIT_Z);
|
|
||||||
|
|
||||||
// Rotates first around z, then y, then x
|
|
||||||
node->setOrientation(xr*yr*zr);
|
|
||||||
|
|
||||||
// Finally, load the NIF mesh and attach it to the node
|
|
||||||
NIFLoader::load(mesh);
|
|
||||||
MovableObject *ent = scene.getMgr()->createEntity(mesh);
|
|
||||||
node->attachObject(ent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CellRender::show()
|
|
||||||
{
|
|
||||||
// If already loaded, just make the cell visible.
|
|
||||||
if(base)
|
|
||||||
{
|
|
||||||
base->setVisible(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
base = scene.getRoot()->createChildSceneNode();
|
|
||||||
|
|
||||||
// Loop through all references in the cell
|
// Loop through all references in the cell
|
||||||
insertCellRefList (cell.activators);
|
insertCellRefList (*this, cell.activators);
|
||||||
insertCellRefList (cell.potions);
|
insertCellRefList (*this, cell.potions);
|
||||||
insertCellRefList (cell.appas);
|
insertCellRefList (*this, cell.appas);
|
||||||
insertCellRefList (cell.armors);
|
insertCellRefList (*this, cell.armors);
|
||||||
insertCellRefList (cell.books);
|
insertCellRefList (*this, cell.books);
|
||||||
insertCellRefList (cell.clothes);
|
insertCellRefList (*this, cell.clothes);
|
||||||
insertCellRefList (cell.containers);
|
insertCellRefList (*this, cell.containers);
|
||||||
insertCellRefList (cell.creatures);
|
insertCellRefList (*this, cell.creatures);
|
||||||
insertCellRefList (cell.doors);
|
insertCellRefList (*this, cell.doors);
|
||||||
insertCellRefList (cell.ingreds);
|
insertCellRefList (*this, cell.ingreds);
|
||||||
// insertCellRefList (cell.creatureLists);
|
// insertCellRefList (*this, cell.creatureLists);
|
||||||
// insertCellRefList (cell.itemLists);
|
// insertCellRefList (*this, cell.itemLists);
|
||||||
insertCellRefList (cell.lights);
|
insertCellRefList (*this, cell.lights);
|
||||||
insertCellRefList (cell.lockpicks);
|
insertCellRefList (*this, cell.lockpicks);
|
||||||
insertCellRefList (cell.miscItems);
|
insertCellRefList (*this, cell.miscItems);
|
||||||
insertCellRefList (cell.npcs);
|
insertCellRefList (*this, cell.npcs);
|
||||||
insertCellRefList (cell.probes);
|
insertCellRefList (*this, cell.probes);
|
||||||
insertCellRefList (cell.repairs);
|
insertCellRefList (*this, cell.repairs);
|
||||||
insertCellRefList (cell.statics);
|
insertCellRefList (*this, cell.statics);
|
||||||
insertCellRefList (cell.weapons);
|
insertCellRefList (*this, cell.weapons);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CellRender::hide()
|
template<>
|
||||||
|
void MWRender::insertObj(CellRender& cellRender, const ESMS::LiveCellRef<ESM::Light>& liveRef)
|
||||||
{
|
{
|
||||||
if(base)
|
assert (liveRef.base != NULL);
|
||||||
base->setVisible(false);
|
const std::string &model = liveRef.base->model;
|
||||||
|
if(!model.empty())
|
||||||
|
{
|
||||||
|
cellRender.insertBegin (liveRef.ref);
|
||||||
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
|
cellRender.insertEnd();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CellRender::destroy()
|
|
||||||
{
|
|
||||||
if(base)
|
|
||||||
{
|
|
||||||
base->removeAndDestroyAllChildren();
|
|
||||||
scene.getMgr()->destroySceneNode(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
base = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Magic function from the internets. Might need this later.
|
|
||||||
/*
|
|
||||||
void Scene::DestroyAllAttachedMovableObjects( SceneNode* i_pSceneNode )
|
|
||||||
{
|
|
||||||
if ( !i_pSceneNode )
|
|
||||||
{
|
|
||||||
ASSERT( false );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy all the attached objects
|
|
||||||
SceneNode::ObjectIterator itObject = i_pSceneNode->getAttachedObjectIterator();
|
|
||||||
|
|
||||||
while ( itObject.hasMoreElements() )
|
|
||||||
{
|
|
||||||
MovableObject* pObject = static_cast<MovableObject*>(itObject.getNext());
|
|
||||||
i_pSceneNode->getCreator()->destroyMovableObject( pObject );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recurse to child SceneNodes
|
|
||||||
SceneNode::ChildNodeIterator itChild = i_pSceneNode->getChildIterator();
|
|
||||||
|
|
||||||
while ( itChild.hasMoreElements() )
|
|
||||||
{
|
|
||||||
SceneNode* pChildNode = static_cast<SceneNode*>(itChild.getNext());
|
|
||||||
DestroyAllAttachedMovableObjects( pChildNode );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
|
@ -8,60 +8,52 @@
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
/**
|
/// Base class for cell render, that implements inserting references into a cell in a
|
||||||
This class is responsible for inserting meshes and other
|
/// cell type- and render-engine-independent way.
|
||||||
rendering objects from the given cell into the given rendering
|
|
||||||
scene.
|
|
||||||
|
|
||||||
TODO FIXME: Doesn't do full cleanup yet.
|
|
||||||
*/
|
|
||||||
class CellRender
|
class CellRender
|
||||||
{
|
{
|
||||||
const ESMS::CellStore &cell;
|
|
||||||
MWScene &scene;
|
|
||||||
|
|
||||||
/// The scene node that contains all objects belonging to this
|
|
||||||
/// cell.
|
|
||||||
Ogre::SceneNode *base;
|
|
||||||
|
|
||||||
void insertMesh(const std::string &mesh, // NIF file
|
|
||||||
const ESMS::CellRef &ref); // Reference information
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void insertObj(const T& liveRef)
|
|
||||||
{
|
|
||||||
assert (liveRef.base != NULL);
|
|
||||||
const std::string &model = liveRef.base->model;
|
|
||||||
if(!model.empty())
|
|
||||||
insertMesh ("meshes\\" + model, liveRef.ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void insertCellRefList (const T& cellRefList)
|
|
||||||
{
|
|
||||||
for(typename T::List::const_iterator it = cellRefList.list.begin();
|
|
||||||
it != cellRefList.list.end(); it++)
|
|
||||||
{
|
|
||||||
insertObj (*it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CellRender(const ESMS::CellStore &_cell,
|
CellRender() {}
|
||||||
MWScene &_scene)
|
virtual ~CellRender() {}
|
||||||
: cell(_cell), scene(_scene), base(NULL) {}
|
|
||||||
~CellRender() { destroy(); }
|
|
||||||
|
|
||||||
/// Make the cell visible. Load the cell if necessary.
|
/// start inserting a new reference.
|
||||||
void show();
|
virtual void insertBegin (const ESMS::CellRef &ref) = 0;
|
||||||
|
|
||||||
/// Remove the cell from rendering, but don't remove it from
|
/// insert a mesh related to the most recent insertBegin call.
|
||||||
/// memory.
|
virtual void insertMesh(const std::string &mesh) = 0;
|
||||||
void hide();
|
|
||||||
|
/// finish inserting a new reference and return a handle to it.
|
||||||
/// Destroy all rendering objects connected with this cell.
|
virtual std::string insertEnd() = 0;
|
||||||
void destroy();
|
|
||||||
|
void insertCell(const ESMS::CellStore &cell);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void insertObj(CellRender& cellRender, const T& liveRef)
|
||||||
|
{
|
||||||
|
assert (liveRef.base != NULL);
|
||||||
|
const std::string &model = liveRef.base->model;
|
||||||
|
if(!model.empty())
|
||||||
|
{
|
||||||
|
cellRender.insertBegin (liveRef.ref);
|
||||||
|
cellRender.insertMesh ("meshes\\" + model);
|
||||||
|
cellRender.insertEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void insertObj(CellRender& cellRender, const ESMS::LiveCellRef<ESM::Light>& liveRef);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void insertCellRefList (CellRender& cellRender, const T& cellRefList)
|
||||||
|
{
|
||||||
|
for(typename T::List::const_iterator it = cellRefList.list.begin();
|
||||||
|
it != cellRefList.list.end(); it++)
|
||||||
|
{
|
||||||
|
insertObj (cellRender, *it);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
124
game/mwrender/interior.cpp
Normal file
124
game/mwrender/interior.cpp
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
#include "interior.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include <OgreEntity.h>
|
||||||
|
|
||||||
|
#include "nifogre/ogre_nif_loader.hpp"
|
||||||
|
|
||||||
|
using namespace MWRender;
|
||||||
|
using namespace Ogre;
|
||||||
|
using namespace ESMS;
|
||||||
|
|
||||||
|
// start inserting a new reference.
|
||||||
|
|
||||||
|
void InteriorCellRender::insertBegin (const ESMS::CellRef &ref)
|
||||||
|
{
|
||||||
|
assert (!insert);
|
||||||
|
|
||||||
|
// Create and place scene node for this object
|
||||||
|
insert = base->createChildSceneNode();
|
||||||
|
|
||||||
|
const float *f = ref.pos.pos;
|
||||||
|
insert->setPosition(f[0], f[1], f[2]);
|
||||||
|
insert->setScale(ref.scale, ref.scale, ref.scale);
|
||||||
|
|
||||||
|
// Convert MW rotation to a quaternion:
|
||||||
|
f = ref.pos.rot;
|
||||||
|
|
||||||
|
// Rotate around X axis
|
||||||
|
Quaternion xr(Radian(-f[0]), Vector3::UNIT_X);
|
||||||
|
|
||||||
|
// Rotate around Y axis
|
||||||
|
Quaternion yr(Radian(-f[1]), Vector3::UNIT_Y);
|
||||||
|
|
||||||
|
// Rotate around Z axis
|
||||||
|
Quaternion zr(Radian(-f[2]), Vector3::UNIT_Z);
|
||||||
|
|
||||||
|
// Rotates first around z, then y, then x
|
||||||
|
insert->setOrientation(xr*yr*zr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert a mesh related to the most recent insertBegin call.
|
||||||
|
|
||||||
|
void InteriorCellRender::insertMesh(const std::string &mesh)
|
||||||
|
{
|
||||||
|
assert (insert);
|
||||||
|
|
||||||
|
NIFLoader::load(mesh);
|
||||||
|
MovableObject *ent = scene.getMgr()->createEntity(mesh);
|
||||||
|
insert->attachObject(ent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// finish inserting a new reference and return a handle to it.
|
||||||
|
|
||||||
|
std::string InteriorCellRender::insertEnd()
|
||||||
|
{
|
||||||
|
assert (insert);
|
||||||
|
|
||||||
|
std::string handle = insert->getName();
|
||||||
|
|
||||||
|
insert = 0;
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteriorCellRender::show()
|
||||||
|
{
|
||||||
|
// If already loaded, just make the cell visible.
|
||||||
|
if(base)
|
||||||
|
{
|
||||||
|
base->setVisible(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base = scene.getRoot()->createChildSceneNode();
|
||||||
|
|
||||||
|
insertCell(cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteriorCellRender::hide()
|
||||||
|
{
|
||||||
|
if(base)
|
||||||
|
base->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteriorCellRender::destroy()
|
||||||
|
{
|
||||||
|
if(base)
|
||||||
|
{
|
||||||
|
base->removeAndDestroyAllChildren();
|
||||||
|
scene.getMgr()->destroySceneNode(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
base = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Magic function from the internets. Might need this later.
|
||||||
|
/*
|
||||||
|
void Scene::DestroyAllAttachedMovableObjects( SceneNode* i_pSceneNode )
|
||||||
|
{
|
||||||
|
if ( !i_pSceneNode )
|
||||||
|
{
|
||||||
|
ASSERT( false );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy all the attached objects
|
||||||
|
SceneNode::ObjectIterator itObject = i_pSceneNode->getAttachedObjectIterator();
|
||||||
|
|
||||||
|
while ( itObject.hasMoreElements() )
|
||||||
|
{
|
||||||
|
MovableObject* pObject = static_cast<MovableObject*>(itObject.getNext());
|
||||||
|
i_pSceneNode->getCreator()->destroyMovableObject( pObject );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recurse to child SceneNodes
|
||||||
|
SceneNode::ChildNodeIterator itChild = i_pSceneNode->getChildIterator();
|
||||||
|
|
||||||
|
while ( itChild.hasMoreElements() )
|
||||||
|
{
|
||||||
|
SceneNode* pChildNode = static_cast<SceneNode*>(itChild.getNext());
|
||||||
|
DestroyAllAttachedMovableObjects( pChildNode );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
75
game/mwrender/interior.hpp
Normal file
75
game/mwrender/interior.hpp
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#ifndef _GAME_RENDER_INTERIOR_H
|
||||||
|
#define _GAME_RENDER_INTERIOR_H
|
||||||
|
|
||||||
|
#include "cell.hpp"
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
This class is responsible for inserting meshes and other
|
||||||
|
rendering objects from the given cell into the given rendering
|
||||||
|
scene.
|
||||||
|
|
||||||
|
TODO FIXME: Doesn't do full cleanup yet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class InteriorCellRender : private CellRender
|
||||||
|
{
|
||||||
|
const ESMS::CellStore &cell;
|
||||||
|
MWScene &scene;
|
||||||
|
|
||||||
|
/// The scene node that contains all objects belonging to this
|
||||||
|
/// cell.
|
||||||
|
Ogre::SceneNode *base;
|
||||||
|
|
||||||
|
Ogre::SceneNode *insert;
|
||||||
|
|
||||||
|
/// start inserting a new reference.
|
||||||
|
virtual void insertBegin (const ESMS::CellRef &ref);
|
||||||
|
|
||||||
|
/// insert a mesh related to the most recent insertBegin call.
|
||||||
|
virtual void insertMesh(const std::string &mesh);
|
||||||
|
|
||||||
|
/// finish inserting a new reference and return a handle to it.
|
||||||
|
virtual std::string insertEnd();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void insertObj(const T& liveRef)
|
||||||
|
{
|
||||||
|
assert (liveRef.base != NULL);
|
||||||
|
const std::string &model = liveRef.base->model;
|
||||||
|
if(!model.empty())
|
||||||
|
insertMesh ("meshes\\" + model, liveRef.ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void insertCellRefList (const T& cellRefList)
|
||||||
|
{
|
||||||
|
for(typename T::List::const_iterator it = cellRefList.list.begin();
|
||||||
|
it != cellRefList.list.end(); it++)
|
||||||
|
{
|
||||||
|
insertObj (*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
InteriorCellRender(const ESMS::CellStore &_cell, MWScene &_scene)
|
||||||
|
: cell(_cell), scene(_scene), base(NULL), insert(NULL) {}
|
||||||
|
|
||||||
|
virtual ~InteriorCellRender() { destroy(); }
|
||||||
|
|
||||||
|
/// Make the cell visible. Load the cell if necessary.
|
||||||
|
void show();
|
||||||
|
|
||||||
|
/// Remove the cell from rendering, but don't remove it from
|
||||||
|
/// memory.
|
||||||
|
void hide();
|
||||||
|
|
||||||
|
/// Destroy all rendering objects connected with this cell.
|
||||||
|
void destroy();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue