Created cell renderer w/NIF loading. Runs but is WIP.

pull/7/head
Nicolay Korslund 15 years ago
parent e8c6caa0b5
commit 86b78b18f4

@ -11,11 +11,14 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
set(BSA bsa/bsa_archive.cpp bsa/bsa_file.cpp)
set(BSA_HEADER bsa/bsa_archive.hpp bsa/bsa_file.hpp)
set(NIF nif/nif_file.cpp nifogre/ogre_nif_loader.cpp)
set(NIF nif/nif_file.cpp)
set(NIF_HEADER nif/controlled.hpp nif/effect.hpp nif/nif_types.hpp nif/record.hpp
nif/controller.hpp nif/extra.hpp nif/node.hpp nif/record_ptr.hpp
nif/data.hpp nif/nif_file.hpp nif/property.hpp)
set(NIFOGRE nifogre/ogre_nif_loader.cpp)
set(NIFOGRE_HEADER nifogre/ogre_nif_loader.hpp)
set(TOOLS tools/stringops.cpp tools/fileops.cpp)
set(TOOLS_HEADER tools/fileops.hpp tools/slice_array.hpp tools/stringops.hpp)
@ -30,7 +33,7 @@ set(INPUT_HEADER input/oismanager.hpp input/listener.hpp)
set(GAME game/main.cpp game/esm_store/store.cpp game/cell_store.cpp)
set(GAME_HEADER game/cell_store.hpp game/esm_store/reclists.hpp game/esm_store/store.hpp)
set(GAMEREND game/render/mwscene.cpp)
set(GAMEREND game/render/mwscene.cpp game/render/cell.cpp)
set(GAMEREND_HEADER game/render/cell.hpp game/render/mwscene.hpp)
# Platform specific
@ -70,6 +73,9 @@ add_executable(openmw
${TOOLS} ${TOOLS_HEADER}
${OGRE} ${OGRE_HEADER}
${INPUT} ${INPUT_HEADER}
${NIF} ${NIF_HEADER}
${NIFOGRE} ${NIFOGRE_HEADER}
${MANGLE_VFS}
${GAME} ${GAME_HEADER}
${GAMEREND} ${GAMEREND_HEADER})

@ -42,7 +42,8 @@ namespace ESMS
struct CellRefList
{
typedef LiveCellRef<X> LiveRef;
std::list<LiveRef> list;
typedef std::list<LiveRef> List;
List list;
// Search for the given reference in the given reclist from
// ESMStore. Insert the reference into the list if a match is

@ -21,15 +21,24 @@ namespace ESMS
template <typename X>
struct RecListT : RecList
{
typedef std::map<std::string,X> MapType;
typedef std::map<std::string,X*> MapType;
MapType list;
// Load one object of this type
void load(ESMReader &esm, const std::string &id)
{
X &ref = list[id];
ref.load(esm);
X *ref;
if(list.find(id) == list.end())
{
ref = new X;
list[id] = ref;
}
else
ref = list[id];
ref->load(esm);
}
// Find the given object ID, or return NULL if not found.
@ -37,7 +46,7 @@ namespace ESMS
{
if(list.find(id) == list.end())
return NULL;
return &list.find(id)->second;
return list.find(id)->second;
}
int getSize() { return list.size(); }
@ -49,15 +58,24 @@ namespace ESMS
template <typename X>
struct RecIDListT : RecList
{
typedef std::map<std::string,X> MapType;
typedef std::map<std::string,X*> MapType;
MapType list;
void load(ESMReader &esm, const std::string &id)
{
X &ref = list[id];
ref.id = id;
ref.load(esm);
X *ref;
if(list.find(id) == list.end())
{
ref = new X;
list[id] = ref;
}
else
ref = list[id];
ref->id = id;
ref->load(esm);
}
int getSize() { return list.size(); }
@ -73,11 +91,11 @@ namespace ESMS
int getSize() { return count; }
// List of interior cells. Indexed by cell name.
typedef std::map<std::string,Cell> IntCells;
typedef std::map<std::string,Cell*> IntCells;
IntCells intCells;
// List of exterior cells. Indexed as extCells[gridX][gridY].
typedef std::map<int, std::map<int, Cell> > ExtCells;
typedef std::map<int, std::map<int, Cell*> > ExtCells;
ExtCells extCells;
const Cell* findInt(const std::string &id) const
@ -87,7 +105,7 @@ namespace ESMS
if(it == intCells.end())
return NULL;
return &it->second;
return it->second;
}
void load(ESMReader &esm, const std::string &id)
@ -97,13 +115,13 @@ namespace ESMS
count++;
// All cells have a name record, even nameless exterior cells.
Cell cell;
cell.name = id;
Cell *cell = new Cell;
cell->name = id;
// The cell itself takes care of all the hairy details
cell.load(esm);
cell->load(esm);
if(cell.data.flags & Cell::Interior)
if(cell->data.flags & Cell::Interior)
{
// Store interior cell by name
intCells[id] = cell;
@ -111,7 +129,7 @@ namespace ESMS
else
{
// Store exterior cells by grid position
extCells[cell.data.gridX][cell.data.gridY] = cell;
extCells[cell->data.gridX][cell->data.gridY] = cell;
}
}
};

@ -35,18 +35,22 @@ void maintest()
// This parses the ESM file and loads a sample cell
esm.open(esmFile);
store.load(esm);
cell.loadInt("Beshara", store, esm);
// Create the window
ogre.createWindow("OpenMW");
cout << "\nSetting up cell rendering (not done)\n";
cout << "\nSetting up cell rendering\n";
// Sets up camera, scene manager etc
Render::MWScene scene(ogre);
// This doesn't do anything yet.
Render::CellRender rend(cell);
// This connects the cell data with the rendering scene.
Render::CellRender rend(cell, scene);
// Load the cell and insert it into the renderer
rend.show();
cout << "Setting up input system\n";

@ -0,0 +1,129 @@
#include "cell.hpp"
#include <OgreEntity.h>
#include "nifogre/ogre_nif_loader.hpp"
using namespace Render;
using namespace Ogre;
using namespace ESMS;
// Inserts one mesh into the scene
static void insertObj(SceneNode *base, // Parent scene node
SceneManager *mgr, // Scene manager
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 = mgr->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 statics in the cell
CellRefList<Static>::List::const_iterator it;
for(it = cell.statics.list.begin();
it != cell.statics.list.end();
it++)
{
assert(it->base != NULL);
insertObj(base, scene.getMgr(),
"meshes\\" + it->base->model,
it->ref);
}
/*
// Containers
CellRefList<Container>::List::const_iterator it;
for(it = cell.containers.list.begin();
it != cell.containers.list.end();
it++)
{
assert(it->base != NULL);
cout << "refID = " << it->ref.refID << " x" << it->ref.scale << endl;
cout << "flags = " << it->base->flags << endl;
}
*/
}
void CellRender::hide()
{
if(base)
base->setVisible(false);
}
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 );
}
}
*/

@ -2,16 +2,40 @@
#define _GAME_RENDER_CELL_H
#include "../cell_store.hpp"
#include "mwscene.hpp"
namespace Render
{
/**
This class is responsible for inserting meshes and other
rendering objects from the given cell into the given rendering
scene.
*/
class CellRender
{
const ESMS::CellStore *cell;
const ESMS::CellStore &cell;
MWScene &scene;
/// The scene node that contains all objects belonging to this
/// cell.
Ogre::SceneNode *base;
public:
CellRender(const ESMS::CellStore &_cell)
: cell(&_cell) {}
CellRender(const ESMS::CellStore &_cell,
MWScene &_scene)
: cell(_cell), scene(_scene), base(NULL) {}
~CellRender() { 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();
};
}

@ -32,6 +32,9 @@ namespace Render
public:
MWScene(OgreRenderer &_rend);
Ogre::SceneNode *getRoot() { return mwRoot; }
Ogre::SceneManager *getMgr() { return sceneMgr; }
};
}

@ -46,13 +46,13 @@ using namespace Mangle::VFS;
// tell Ogre to look (eg. in zip or rar files.) It's also used to
// check for the existence of texture files, so we can exchange the
// extension from .tga to .dds if the texture is missing.
OgreVFS *vfs;
static OgreVFS *vfs;
// Singleton instance used by load()
static NIFLoader g_sing;
// Makeshift error reporting system
static string errName;
static void warn(const string &msg)
{
cout << "WARNING (NIF:" << errName << "): " << msg << endl;
@ -615,12 +615,13 @@ void NIFLoader::loadResource(Resource *resource)
mesh->_setBoundingSphereRadius(10);
}
MeshPtr NIFLoader::load(const char* name, const char* group)
MeshPtr NIFLoader::load(const std::string &name,
const std::string &group)
{
MeshManager *m = MeshManager::getSingletonPtr();
// Check if the resource already exists
ResourcePtr ptr = m->getByName(name/*, group*/);
ResourcePtr ptr = m->getByName(name, group);
if(!ptr.isNull())
return MeshPtr(ptr);

@ -47,7 +47,8 @@ struct NIFLoader : Ogre::ManualResourceLoader
{
void loadResource(Ogre::Resource *resource);
static Ogre::MeshPtr load(const char* name, const char* group="General");
static Ogre::MeshPtr load(const std::string &name,
const std::string &group="General");
};
#endif

Loading…
Cancel
Save