forked from mirror/openmw-tes3mp
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_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_HEADER game/mwrender/cell.hpp game/mwrender/mwscene.hpp)
|
||||
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
|
||||
game/mwrender/interior.hpp)
|
||||
|
||||
set(ESM_HEADER esm/defs.hpp esm/loadcell.hpp esm/loadfact.hpp esm/loadltex.hpp
|
||||
esm/loadskil.hpp
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "ogre/renderer.hpp"
|
||||
#include "tools/fileops.hpp"
|
||||
|
||||
#include "mwrender/cell.hpp"
|
||||
#include "mwrender/interior.hpp"
|
||||
#include "mwrender/mwscene.hpp"
|
||||
#include "mwinput/inputmanager.hpp"
|
||||
|
||||
|
@ -59,7 +59,7 @@ void maintest (std::string dataDir, const std::string& cellName)
|
|||
MWRender::MWScene scene(ogre);
|
||||
|
||||
// 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
|
||||
rend.show();
|
||||
|
|
|
@ -1,122 +1,42 @@
|
|||
#include "cell.hpp"
|
||||
|
||||
#include <OgreEntity.h>
|
||||
|
||||
#include "nifogre/ogre_nif_loader.hpp"
|
||||
|
||||
using namespace MWRender;
|
||||
using namespace Ogre;
|
||||
using namespace ESMS;
|
||||
|
||||
// Inserts one mesh into the scene
|
||||
void CellRender::insertMesh(const std::string &mesh, // NIF file
|
||||
const CellRef &ref) // Reference information
|
||||
void CellRender::insertCell(const ESMS::CellStore &cell)
|
||||
{
|
||||
// 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
|
||||
insertCellRefList (cell.activators);
|
||||
insertCellRefList (cell.potions);
|
||||
insertCellRefList (cell.appas);
|
||||
insertCellRefList (cell.armors);
|
||||
insertCellRefList (cell.books);
|
||||
insertCellRefList (cell.clothes);
|
||||
insertCellRefList (cell.containers);
|
||||
insertCellRefList (cell.creatures);
|
||||
insertCellRefList (cell.doors);
|
||||
insertCellRefList (cell.ingreds);
|
||||
// insertCellRefList (cell.creatureLists);
|
||||
// insertCellRefList (cell.itemLists);
|
||||
insertCellRefList (cell.lights);
|
||||
insertCellRefList (cell.lockpicks);
|
||||
insertCellRefList (cell.miscItems);
|
||||
insertCellRefList (cell.npcs);
|
||||
insertCellRefList (cell.probes);
|
||||
insertCellRefList (cell.repairs);
|
||||
insertCellRefList (cell.statics);
|
||||
insertCellRefList (cell.weapons);
|
||||
insertCellRefList (*this, cell.activators);
|
||||
insertCellRefList (*this, cell.potions);
|
||||
insertCellRefList (*this, cell.appas);
|
||||
insertCellRefList (*this, cell.armors);
|
||||
insertCellRefList (*this, cell.books);
|
||||
insertCellRefList (*this, cell.clothes);
|
||||
insertCellRefList (*this, cell.containers);
|
||||
insertCellRefList (*this, cell.creatures);
|
||||
insertCellRefList (*this, cell.doors);
|
||||
insertCellRefList (*this, cell.ingreds);
|
||||
// insertCellRefList (*this, cell.creatureLists);
|
||||
// insertCellRefList (*this, cell.itemLists);
|
||||
insertCellRefList (*this, cell.lights);
|
||||
insertCellRefList (*this, cell.lockpicks);
|
||||
insertCellRefList (*this, cell.miscItems);
|
||||
insertCellRefList (*this, cell.npcs);
|
||||
insertCellRefList (*this, cell.probes);
|
||||
insertCellRefList (*this, cell.repairs);
|
||||
insertCellRefList (*this, cell.statics);
|
||||
insertCellRefList (*this, cell.weapons);
|
||||
}
|
||||
|
||||
void CellRender::hide()
|
||||
template<>
|
||||
void MWRender::insertObj(CellRender& cellRender, const ESMS::LiveCellRef<ESM::Light>& liveRef)
|
||||
{
|
||||
if(base)
|
||||
base->setVisible(false);
|
||||
assert (liveRef.base != NULL);
|
||||
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
|
||||
{
|
||||
/**
|
||||
This class is responsible for inserting meshes and other
|
||||
rendering objects from the given cell into the given rendering
|
||||
scene.
|
||||
/// Base class for cell render, that implements inserting references into a cell in a
|
||||
/// cell type- and render-engine-independent way.
|
||||
|
||||
TODO FIXME: Doesn't do full cleanup yet.
|
||||
*/
|
||||
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:
|
||||
CellRender(const ESMS::CellStore &_cell,
|
||||
MWScene &_scene)
|
||||
: cell(_cell), scene(_scene), base(NULL) {}
|
||||
~CellRender() { destroy(); }
|
||||
CellRender() {}
|
||||
virtual ~CellRender() {}
|
||||
|
||||
/// Make the cell visible. Load the cell if necessary.
|
||||
void show();
|
||||
/// start inserting a new reference.
|
||||
virtual void insertBegin (const ESMS::CellRef &ref) = 0;
|
||||
|
||||
/// Remove the cell from rendering, but don't remove it from
|
||||
/// memory.
|
||||
void hide();
|
||||
|
||||
/// Destroy all rendering objects connected with this cell.
|
||||
void destroy();
|
||||
/// insert a mesh related to the most recent insertBegin call.
|
||||
virtual void insertMesh(const std::string &mesh) = 0;
|
||||
|
||||
/// finish inserting a new reference and return a handle to it.
|
||||
virtual std::string insertEnd() = 0;
|
||||
|
||||
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
|
||||
|
|
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