mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-25 07:56:37 +00:00 
			
		
		
		
	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); | ||||
| } | ||||
| 
 | ||||
| void CellRender::destroy() | ||||
|   assert (liveRef.base != NULL); | ||||
|   const std::string &model = liveRef.base->model; | ||||
|   if(!model.empty()) | ||||
|   { | ||||
|   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 ); | ||||
|     cellRender.insertBegin (liveRef.ref); | ||||
|     cellRender.insertMesh ("meshes\\" + model); | ||||
|     cellRender.insertEnd(); | ||||
|   }   | ||||
| } | ||||
| */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
|   public: | ||||
|     CellRender() {} | ||||
|     virtual ~CellRender() {} | ||||
| 
 | ||||
|     /// The scene node that contains all objects belonging to this
 | ||||
|     /// cell.
 | ||||
|     Ogre::SceneNode *base; | ||||
|     /// start inserting a new reference.
 | ||||
|     virtual void insertBegin (const ESMS::CellRef &ref) = 0; | ||||
| 
 | ||||
|     void insertMesh(const std::string &mesh,   // NIF file
 | ||||
|                     const ESMS::CellRef &ref); // Reference information
 | ||||
|     /// 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(const T& liveRef) | ||||
|   void insertObj(CellRender& cellRender, const T& liveRef) | ||||
|   { | ||||
|       assert (liveRef.base != NULL); | ||||
|       const std::string &model = liveRef.base->model; | ||||
|       if(!model.empty()) | ||||
|           insertMesh ("meshes\\" + model, liveRef.ref); | ||||
|       { | ||||
|         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 (const T& cellRefList) | ||||
|   void insertCellRefList (CellRender& cellRender, const T& cellRefList) | ||||
|   { | ||||
|     for(typename T::List::const_iterator it = cellRefList.list.begin(); | ||||
|         it != cellRefList.list.end(); it++) | ||||
|     { | ||||
|         insertObj (*it); | ||||
|       insertObj (cellRender, *it); | ||||
|     }     | ||||
|   }     | ||||
|                        | ||||
|   public: | ||||
|     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(); | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| #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