diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 37ecc3eaa..bbee7498a 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -16,7 +16,7 @@ set(GAME_HEADER source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender - rendering_manager mwscene cellimp interior exterior sky player + renderingmanager debugging sky player animation npcanimation creatureanimation actors objects renderinginterface ) add_openmw_dir (mwinput @@ -36,6 +36,7 @@ add_openmw_dir (mwscript locals scriptmanager compilercontext interpretercontext cellextensions miscextensions guiextensions soundextensions skyextensions statsextensions containerextensions aiextensions controlextensions extensions globalscripts ref dialogueextensions + animationextensions ) add_openmw_dir (mwsound diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index f4a1c407e..e1a16accf 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "mwinput/inputmanager.hpp" @@ -46,6 +47,7 @@ #include "mwmechanics/mechanicsmanager.hpp" + void OMW::Engine::executeLocalScripts() { MWWorld::LocalScripts& localScripts = mEnvironment.mWorld->getLocalScripts(); @@ -69,6 +71,7 @@ void OMW::Engine::executeLocalScripts() void OMW::Engine::updateFocusReport (float duration) { + if ((mFocusTDiff += duration)>0.25) { mFocusTDiff = 0; @@ -81,8 +84,10 @@ void OMW::Engine::updateFocusReport (float duration) { MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle); - if (!ptr.isEmpty()) + if (!ptr.isEmpty()){ name = MWWorld::Class::get (ptr).getName (ptr); + + } } if (name!=mFocusName) @@ -97,6 +102,13 @@ void OMW::Engine::updateFocusReport (float duration) } } +void OMW::Engine::setAnimationVerbose(bool animverbose){ + if(animverbose){ + NifOgre::NIFLoader::getSingletonPtr()->setOutputAnimFiles(true); + NifOgre::NIFLoader::getSingletonPtr()->setVerbosePath(mCfgMgr.getLogPath().string()); + } +} + bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) { try @@ -135,6 +147,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) mEnvironment.mWorld->advanceTime ( mEnvironment.mFrameDuration*mEnvironment.mWorld->getTimeScaleFactor()/3600); + if (changed) // keep change flag for another frame, if cell changed happend in local script mEnvironment.mWorld->markCellAsUnchanged(); @@ -287,6 +300,7 @@ void OMW::Engine::setReportFocus (bool report) void OMW::Engine::go() { + mFocusTDiff = 0; assert (!mEnvironment.mWorld); assert (!mCellName.empty()); assert (!mMaster.empty()); @@ -329,6 +343,7 @@ void OMW::Engine::go() // Set up the GUI system mGuiManager = new OEngine::GUI::MyGUIManager(mOgre->getWindow(), mOgre->getScene(), false, mCfgMgr.getLogPath().string() + std::string("/")); + // Create window manager - this manages all the MW-specific GUI windows MWScript::registerExtensions (mExtensions); diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 259c44d11..02d108f0a 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -158,6 +158,8 @@ namespace OMW /// Font encoding void setEncoding(const std::string& encoding); + void setAnimationVerbose(bool animverbose); + private: Cfg::ConfigurationManager& mCfgMgr; }; diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index acb852020..2d0c8e44b 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -78,6 +78,9 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Cfg::Configuratio ("fps", boost::program_options::value()->implicit_value(1) ->default_value(0), "fps counter detail (0 = off, 1 = fps counter, 2 = full detail)") + ("anim-verbose", boost::program_options::value()->implicit_value(true) + ->default_value(false), "output animation indices files") + ("debug", boost::program_options::value()->implicit_value(true) ->default_value(false), "debug mode") @@ -206,6 +209,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Cfg::Configuratio engine.setScriptsVerbosity(variables["script-verbose"].as()); engine.setCompileAll(variables["script-all"].as()); engine.setReportFocus(variables["report-focus"].as()); + engine.setAnimationVerbose(variables["anim-verbose"].as()); return true; } diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 4d4b7aeaa..6749a2bfd 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -1,5 +1,6 @@ #include "activator.hpp" +#include "../mwrender/objects.hpp" #include @@ -7,27 +8,39 @@ #include "../mwworld/ptr.hpp" -#include "../mwrender/cellimp.hpp" namespace MWClass { - void Activator::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); } } + void Activator::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + std::string Activator::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp index 3b48796ac..08be8a5ff 100644 --- a/apps/openmw/mwclass/activator.hpp +++ b/apps/openmw/mwclass/activator.hpp @@ -9,10 +9,11 @@ namespace MWClass { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index ddf96d1be..30b308e70 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -8,29 +8,41 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwrender/cellimp.hpp" #include "containerutil.hpp" namespace MWClass { - void Apparatus::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Apparatus::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); } } + void Apparatus::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + std::string Apparatus::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index c2e6e25e1..4c8a2c0e2 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -2,6 +2,7 @@ #define GAME_MWCLASS_APPARATUS_H #include "../mwworld/class.hpp" +#include "../mwrender/objects.hpp" namespace MWClass { @@ -9,10 +10,11 @@ namespace MWClass { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 9452fea16..a8a431acf 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -8,29 +8,40 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwrender/cellimp.hpp" #include "containerutil.hpp" namespace MWClass { - void Armor::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Armor::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); } } + void Armor::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + std::string Armor::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 040342a69..c5f9812b7 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -2,6 +2,7 @@ #define GAME_MWCLASS_ARMOR_H #include "../mwworld/class.hpp" +#include "../mwrender/objects.hpp" namespace MWClass { @@ -9,10 +10,11 @@ namespace MWClass { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index c2d3c4aa8..011fd2c32 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -8,29 +8,41 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwrender/cellimp.hpp" #include "containerutil.hpp" namespace MWClass { - void Book::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Book::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); } } + void Book::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + std::string Book::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index 70d1bca3b..f0e38cceb 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -2,6 +2,7 @@ #define GAME_MWCLASS_BOOK_H #include "../mwworld/class.hpp" +#include "../mwrender/objects.hpp" namespace MWClass { @@ -9,10 +10,11 @@ namespace MWClass { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 7c69573ed..0214c72ad 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -8,29 +8,41 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwrender/cellimp.hpp" #include "containerutil.hpp" namespace MWClass { - void Clothing::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Clothing::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); } } + void Clothing::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + std::string Clothing::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index fb88e25df..76c2c4a3e 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -2,6 +2,7 @@ #define GAME_MWCLASS_CLOTHING_H #include "../mwworld/class.hpp" +#include "../mwrender/objects.hpp" namespace MWClass { @@ -9,10 +10,11 @@ namespace MWClass { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index ad2ab8d65..4157ce17a 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -7,27 +7,38 @@ #include "../mwworld/ptr.hpp" -#include "../mwrender/cellimp.hpp" - namespace MWClass { - void Container::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Container::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); } } + void Container::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + std::string Container::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index de54a9e68..01763870a 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -2,6 +2,7 @@ #define GAME_MWCLASS_CONTAINER_H #include "../mwworld/class.hpp" +#include "../mwrender/objects.hpp" namespace MWClass { @@ -9,10 +10,11 @@ namespace MWClass { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 2e223c918..5aa203a49 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -9,7 +9,6 @@ #include "../mwworld/actiontalk.hpp" #include "../mwworld/environment.hpp" -#include "../mwrender/cellimp.hpp" #include "../mwmechanics/mechanicsmanager.hpp" @@ -23,21 +22,34 @@ namespace MWClass return ref->base->mId; } - void Creature::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - ESMS::LiveCellRef *ref = + + /*ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) - { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - cellRender.insertMesh("meshes\\" + model); - cellRender.insertActorPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + {*/ + MWRender::Actors& actors = renderingInterface.getActors(); + actors.insertCreature(ptr); + + } + + void Creature::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertActorPhysics(ptr, "meshes\\" + model); } + } void Creature::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 9f6708f40..b7b654bc0 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -2,6 +2,9 @@ #define GAME_MWCLASS_CREATURE_H #include "../mwworld/class.hpp" +#include "../mwrender/renderinginterface.hpp" +#include "../mwrender/actors.hpp" + namespace MWClass { @@ -12,10 +15,11 @@ namespace MWClass virtual std::string getId (const MWWorld::Ptr& ptr) const; ///< Return ID of \a ptr - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const; ///< Enable reference; only does the non-rendering part diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index e32e3ef4e..26436a012 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -12,29 +12,42 @@ #include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" -#include "../mwrender/cellimp.hpp" +#include "../mwrender/objects.hpp" #include namespace MWClass { - void Door::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Door::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - ESMS::LiveCellRef *ref = + ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); } } + void Door::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + std::string Door::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index aecb117d3..c230cf357 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -2,6 +2,7 @@ #define GAME_MWCLASS_DOOR_H #include "../mwworld/class.hpp" +#include "../mwrender/objects.hpp" namespace MWClass { @@ -9,10 +10,11 @@ namespace MWClass { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index e2c9b072f..5e55010eb 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -8,29 +8,42 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwrender/cellimp.hpp" #include "containerutil.hpp" namespace MWClass { - void Ingredient::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Ingredient::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); } } + void Ingredient::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + std::string Ingredient::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index 8b781ba2f..47bd1a9e5 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -2,6 +2,7 @@ #define GAME_MWCLASS_INGREDIENT_H #include "../mwworld/class.hpp" +#include "../mwrender/objects.hpp" namespace MWClass { @@ -9,10 +10,11 @@ namespace MWClass { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index f32378002..3890899b0 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -10,41 +10,48 @@ #include "../mwworld/nullaction.hpp" #include "../mwworld/environment.hpp" -#include "../mwrender/cellimp.hpp" - #include "../mwsound/soundmanager.hpp" #include "containerutil.hpp" namespace MWClass { - void Light::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Light::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - - // Extract the color and convert to floating point + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); const int color = ref->base->data.color; - const float r = ((color >> 0) & 0xFF) / 255.0f; - const float g = ((color >> 8) & 0xFF) / 255.0f; + const float r = ((color >> 0) & 0xFF) / 255.0f; + const float g = ((color >> 8) & 0xFF) / 255.0f; const float b = ((color >> 16) & 0xFF) / 255.0f; const float radius = float (ref->base->data.radius); - cellRender.insertLight (r, g, b, radius); - - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + objects.insertLight (ptr, r, g, b, radius); } } + void Light::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + void Light::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 5a1a15b1d..34421ff51 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -2,6 +2,7 @@ #define GAME_MWCLASS_LIGHT_H #include "../mwworld/class.hpp" +#include "../mwrender/objects.hpp" namespace MWClass { @@ -9,10 +10,11 @@ namespace MWClass { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const; ///< Enable reference; only does the non-rendering part /// \attention This is not the same as the script instruction with the same name. References diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 3a94fce26..636a8f0be 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -8,29 +8,41 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwrender/cellimp.hpp" - #include "containerutil.hpp" namespace MWClass { - void Lockpick::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Lockpick::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); } } + void Lockpick::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + + std::string Lockpick::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index bb9866b8c..c5f1539b4 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -2,6 +2,7 @@ #define GAME_MWCLASS_LOCKPICK_H #include "../mwworld/class.hpp" +#include "../mwrender/objects.hpp" namespace MWClass { @@ -9,10 +10,11 @@ namespace MWClass { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 84560d009..a2642d8d5 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -8,29 +8,40 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwrender/cellimp.hpp" - #include "containerutil.hpp" namespace MWClass { - void Miscellaneous::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); } } + void Miscellaneous::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + std::string Miscellaneous::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index 81262cbee..36ee2c1b2 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -2,6 +2,7 @@ #define GAME_MWCLASS_MISC_H #include "../mwworld/class.hpp" +#include "../mwrender/objects.hpp" namespace MWClass { @@ -9,10 +10,11 @@ namespace MWClass { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 83161ebeb..2b98a3d60 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -11,8 +11,6 @@ #include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" -#include "../mwrender/cellimp.hpp" - #include "../mwmechanics/mechanicsmanager.hpp" #include @@ -32,229 +30,31 @@ namespace MWClass return ref->base->mId; } - void Npc::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { - //Ogre::SceneNode *chest; + renderingInterface.getActors().insertNPC(ptr); + } + + void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + + ESMS::LiveCellRef *ref = ptr.get(); - //Store scenenodes by npc's name + bodypart [0] , npc's name + bodypart [1] - //Ex. Fargothchest , Fargothneck assert (ref->base != NULL); - - std::string hairID = ref->base->hair; - std::string headID = ref->base->head; - - // very ugly workaround to stop OGRE from chocking on non-unique scene node handles - static int uniqueId = 0; - - std::ostringstream stream; - stream << "npc$" << uniqueId++; - - std::string npcName = stream.str(); // ref->base->name; - //std::cout << "NPC: " << npcName << "\n"; - - //get the part of the bodypart id which describes the race and the gender - std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); - std::string headModel = "meshes\\" + - environment.mWorld->getStore().bodyParts.find(headID)->model; - - std::string hairModel = "meshes\\" + - environment.mWorld->getStore().bodyParts.find(hairID)->model; - - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); + std::string headID = ref->base->head; + std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); + bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; - //TODO: define consts for each bodypart e.g. chest, foot, wrist... and put the parts in the - // right place - const ESM::BodyPart *bodyPart = - environment.mWorld->getStore().bodyParts.search (bodyRaceID + "chest"); - - //bodyPart->model-> - Ogre::Vector3 pos = Ogre::Vector3( 20, 20, 20); - Ogre::Vector3 axis = Ogre::Vector3( 0, 0, 1); - Ogre::Radian angle = Ogre::Radian(0); - - std::string addresses[6] = {"", "", "", "","", ""}; - std::string addresses2[6] = {"", "", "", "", "", ""}; - std::string upperleft[5] = {"", "", "", "", ""}; - std::string upperright[5] = {"", "", "", "", ""}; - std::string neckandup[5] = {"", "", "","",""}; - int numbers = 0; - int uppernumbers = 0; - int neckNumbers = 0; - - if (bodyPart){ - - cellRender.insertMesh("meshes\\" + bodyPart->model, pos, axis, angle, npcName + "chest", addresses, numbers, true); //2 0 - addresses2[numbers] = npcName + "chest"; - addresses[numbers++] = npcName + "chest"; - upperleft[uppernumbers] = npcName + "chest"; - upperright[uppernumbers++] = npcName + "chest"; - neckandup[neckNumbers++] = npcName + "chest"; - } + std::string smodel = "meshes\\base_anim.nif"; + if(beast) + smodel = "meshes\\base_animkna.nif"; + physics.insertActorPhysics(ptr, smodel); - const ESM::BodyPart *upperleg = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg"); - const ESM::BodyPart *groin = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin"); - const ESM::BodyPart *arm = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper arm"); - const ESM::BodyPart *neck = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "neck"); - const ESM::BodyPart *knee = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "knee"); - const ESM::BodyPart *ankle = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "ankle"); - const ESM::BodyPart *foot = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "foot"); - const ESM::BodyPart *feet = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "feet"); - const ESM::BodyPart *tail = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "tail"); - const ESM::BodyPart *wrist = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "wrist"); - const ESM::BodyPart *forearm = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "forearm"); - const ESM::BodyPart *hand = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "hand.1st"); - const ESM::BodyPart *hands = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands.1st"); - - - Ogre::Vector3 pos2 = Ogre::Vector3( 0, .5, 75); - - if (groin){ - cellRender.insertMesh("meshes\\" + groin->model, pos2, axis, kOgrePi, npcName + "groin", addresses, numbers); - addresses2[numbers] = npcName + "groin"; - addresses[numbers++] = npcName + "groin"; - } - if (tail) { - cellRender.insertMesh("tail\\" + tail->model, Ogre::Vector3(0 , 0, -76), axis, kOgrePi, npcName + "tail", addresses, numbers, "tail"); - } - - - if(upperleg){ - cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( 6, 0, -16), axis, kOgrePi, npcName + "upper leg", addresses, numbers); //-18 - cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( -6, 0, -16), axis, Ogre::Radian(0), npcName + "upper leg2", addresses2, numbers); - addresses2[numbers] = npcName + "upper leg2"; - addresses[numbers++] = npcName + "upper leg"; - cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), addresses, numbers); - } - if(knee) - { - cellRender.insertMesh ("meshes\\" + knee->model, Ogre::Vector3( 0, -1, -23), axis, Ogre::Radian(0), npcName + "knee", addresses, numbers); - //cellRender.rotateMesh(Ogre::Vector3(0, 1, 0), Ogre::Radian (1), npcName + "upper arm"); - cellRender.insertMesh ("meshes\\" + knee->model, Ogre::Vector3( 0, -1, -23), axis, Ogre::Radian(0), npcName + "knee2", addresses2, numbers); - - addresses2[numbers] = npcName + "knee2"; - addresses[numbers++] = npcName + "knee"; - } - if(ankle){ - - cellRender.insertMesh ("meshes\\" + ankle->model, Ogre::Vector3( 0, 0, -20), axis, Ogre::Radian(0), npcName + "ankle", addresses, numbers); //-1 - cellRender.insertMesh ("meshes\\" + ankle->model, Ogre::Vector3( 0,0, -20), axis, Ogre::Radian(0), npcName + "ankle2", addresses2, numbers); //-1 - - addresses2[numbers] = npcName + "ankle2"; - addresses[numbers++] = npcName + "ankle"; - } - if(foot){ - if(bodyRaceID.compare("b_n_khajiit_m_") == 0) - { - feet = foot; - } - else - { - cellRender.insertMesh ("meshes\\" + foot->model, Ogre::Vector3( 0, -4, -15), axis, Ogre::Radian(0), npcName + "foot", addresses, numbers); - - cellRender.insertMesh ("meshes\\" + foot->model, Ogre::Vector3( 0, -4, -15), axis, Ogre::Radian(0), npcName + "foot2", addresses2, numbers); - addresses2[numbers] = npcName + "foot2"; - addresses[numbers++] = npcName + "foot"; - } - //cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), addresses, numbers); - } - if(feet){ - - cellRender.insertMesh ("foot\\" + feet->model, Ogre::Vector3( 7, 4, -16), axis, kOgrePi, npcName + "foot", addresses, numbers); //9, 0, -14 - - cellRender.insertMesh ("foot\\" + feet->model, Ogre::Vector3( 7, 4, -16), axis, kOgrePi, npcName + "foot2", addresses2, numbers); - addresses2[numbers] = npcName + "foot2"; - addresses[numbers++] = npcName + "foot"; - //cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), addresses, numbers); - } - - - if (arm){ - //010 - cellRender.insertMesh("meshes\\" + arm->model, Ogre::Vector3(-12.5, 0, 104), Ogre::Vector3(0, 1, 0), -kOgrePiOverTwo, npcName + "upper arm", upperleft, uppernumbers); //1, 0,.75 - //cellRender.rotateMesh(Ogre::Vector3(1, 0, 0), Ogre::Radian (.45), upperarmpath, 2); //-.5, 0, -.75 - cellRender.insertMesh("meshes\\" + arm->model, Ogre::Vector3(12.5, 0, 105), Ogre::Vector3(-.5, 0, -.75), kOgrePi, npcName + "upper arm2", upperright, uppernumbers); - upperleft[uppernumbers] = npcName + "upper arm"; - upperright[uppernumbers++] = npcName + "upper arm2"; - cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers); //1 -1 1 - cellRender.rotateMesh(Ogre::Vector3(0, .1, 0), kOgrePiOverTwo, upperleft, uppernumbers); - } - - if (forearm) - { - //addresses[1] = npcName + "upper arm"; - cellRender.insertMesh("meshes\\" + forearm->model, Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "forearm", upperleft, uppernumbers); - cellRender.insertMesh("meshes\\" + forearm->model, Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "forearm2", upperright, uppernumbers); - upperleft[uppernumbers] = npcName + "forearm"; - upperright[uppernumbers++] = npcName + "forearm2"; - } - //else - // std::cout << npcName << "has no forearm"; - if (wrist) - { - if(upperleft[uppernumbers - 1].compare(npcName + "upper arm") == 0) - { - cellRender.insertMesh("meshes\\b\\B_N_Argonian_M_Forearm.nif", Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "forearm", upperleft, uppernumbers); - cellRender.insertMesh("meshes\\b\\B_N_Argonian_M_Forearm.nif", Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "forearm2", upperright, uppernumbers); - upperleft[uppernumbers] = npcName + "forearm"; - upperright[uppernumbers++] = npcName + "forearm2"; - - } - cellRender.insertMesh("meshes\\" + wrist->model, Ogre::Vector3(-9.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "wrist", upperleft, uppernumbers); - cellRender.insertMesh("meshes\\" + wrist->model, Ogre::Vector3(-9.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "wrist2", upperright, uppernumbers); - upperleft[uppernumbers] = npcName + "wrist"; - upperright[uppernumbers++] = npcName + "wrist2"; - } - - - if(hand) - { - std::string pass; - if(hand->model.compare("b\\B_N_Dark Elf_F_Hands.1st.NIF")==0 && bodyRaceID.compare("b_n_dark elf_m_") == 0) - pass = "b\\B_N_Dark Elf_M_Hands.1st.NIF"; - else - pass = hand->model; - cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "hand", upperleft, uppernumbers,false); //0, 100, -100 0,0,120 - cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0,0), kOgrePi, npcName + "hand2", upperright, uppernumbers, false); //0, 100, -100 0,0,120 - upperleft[uppernumbers] = npcName + "hand"; - upperright[uppernumbers++] = npcName + "hand2"; - cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers); - cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperright, uppernumbers); - } - if(hands) - { - std::string pass; - if(hands->model.compare("b\\B_N_Redguard_F_Hands.1st.nif")==0 && bodyRaceID.compare("b_n_redguard_m_") == 0) - pass = "b\\B_N_Redguard_M_Hands.1st.nif"; - else if(hands->model.compare("b\\B_N_Imperial_M_Hands.1st.nif") == 0 && bodyRaceID.compare("b_n_nord_m_") == 0) - pass = "b\\B_N_Nord_M_Hands.1st.nif"; - else - pass =hands->model; //-50, 0, -120 - cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1,-110), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "hand", upperleft, uppernumbers, false); //0, 100, -100 42, 0, -110 - cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "hand2", upperright, uppernumbers, false); //0, 100, -100 0,0,120 - upperleft[uppernumbers] = npcName + "hand"; - upperright[uppernumbers++] = npcName + "hand2"; - cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers); - cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperright, uppernumbers); - } - - //neck will reset chest counter - if(neck) - { - cellRender.insertMesh ("meshes\\" + neck->model, Ogre::Vector3( 0, 0, 120), axis, kOgrePi, npcName + "neck", neckandup, neckNumbers); - neckandup[neckNumbers++] = npcName + "neck"; - } - cellRender.insertMesh (headModel, Ogre::Vector3( 0, 0, 5), axis, Ogre::Radian(0), npcName + "head", neckandup, neckNumbers); - neckandup[neckNumbers++] = npcName + "head"; - cellRender.insertMesh (hairModel, Ogre::Vector3( 0, -1, 0), axis, Ogre::Radian(0), npcName + "hair", neckandup, neckNumbers); - - cellRender.insertActorPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } void Npc::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 9f29878da..cc9dbef7f 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -3,6 +3,7 @@ #include "../mwworld/class.hpp" + namespace MWClass { class Npc : public MWWorld::Class @@ -12,10 +13,11 @@ namespace MWClass virtual std::string getId (const MWWorld::Ptr& ptr) const; ///< Return ID of \a ptr - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const; ///< Enable reference; only does the non-rendering part diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 7cd6db223..86d1e2a98 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -8,29 +8,41 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwrender/cellimp.hpp" #include "containerutil.hpp" namespace MWClass { - void Potion::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); } } + void Potion::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + std::string Potion::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index 9bf3b34a8..85678121f 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -2,6 +2,7 @@ #define GAME_MWCLASS_POTION_H #include "../mwworld/class.hpp" +#include "../mwrender/objects.hpp" namespace MWClass { @@ -9,10 +10,11 @@ namespace MWClass { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index b92f5ff26..a09a39e66 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -8,29 +8,42 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwrender/cellimp.hpp" - #include "containerutil.hpp" +#include "../mwrender/objects.hpp" namespace MWClass { - void Probe::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Probe::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); } } + void Probe::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + + std::string Probe::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = @@ -38,7 +51,6 @@ namespace MWClass return ref->base->name; } - boost::shared_ptr Probe::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const { diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index 11399d2f6..d7b9df738 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -3,16 +3,18 @@ #include "../mwworld/class.hpp" + namespace MWClass { class Probe : public MWWorld::Class { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index d52f04e53..f8755b2eb 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -8,29 +8,40 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwrender/cellimp.hpp" - #include "containerutil.hpp" namespace MWClass { - void Repair::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Repair::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); } } + void Repair::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + std::string Repair::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index 3da591e01..1e0ea5178 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -2,6 +2,7 @@ #define GAME_MWCLASS_REPAIR_H #include "../mwworld/class.hpp" +#include "../mwrender/objects.hpp" namespace MWClass { @@ -9,10 +10,11 @@ namespace MWClass { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index 5691f92ba..946da311d 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -5,27 +5,39 @@ #include "../mwworld/ptr.hpp" -#include "../mwrender/cellimp.hpp" namespace MWClass { - void Static::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Static::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData, true); - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); } } + void Static::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + std::string Static::getName (const MWWorld::Ptr& ptr) const { return ""; diff --git a/apps/openmw/mwclass/static.hpp b/apps/openmw/mwclass/static.hpp index abbf6cd5f..be3fdb180 100644 --- a/apps/openmw/mwclass/static.hpp +++ b/apps/openmw/mwclass/static.hpp @@ -2,6 +2,7 @@ #define GAME_MWCLASS_STATIC_H #include "../mwworld/class.hpp" +#include "../mwrender/objects.hpp" namespace MWClass { @@ -9,10 +10,11 @@ namespace MWClass { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 5dcc94fc8..1fbd21f7c 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -8,29 +8,41 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" -#include "../mwrender/cellimp.hpp" #include "containerutil.hpp" namespace MWClass { - void Weapon::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Weapon::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { ESMS::LiveCellRef *ref = ptr.get(); assert (ref->base != NULL); const std::string &model = ref->base->model; + if (!model.empty()) { - MWRender::Rendering rendering (cellRender, ref->ref, ref->mData); - cellRender.insertMesh ("meshes\\" + model); - cellRender.insertObjectPhysics(); - ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertMesh(ptr, "meshes\\" + model); } } + void Weapon::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + + const std::string &model = ref->base->model; + assert (ref->base != NULL); + if(!model.empty()){ + physics.insertObjectPhysics(ptr, "meshes\\" + model); + } + + } + std::string Weapon::getName (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index d9c7653dd..79bc4d4de 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -2,6 +2,7 @@ #define GAME_MWCLASS_WEAPON_H #include "../mwworld/class.hpp" +#include "../mwrender/objects.hpp" namespace MWClass { @@ -9,10 +10,11 @@ namespace MWClass { public: - virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; ///< Add reference into a cell for rendering + virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; + virtual std::string getName (const MWWorld::Ptr& ptr) const; ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. diff --git a/apps/openmw/mwmechanics/mechanicsmanager.cpp b/apps/openmw/mwmechanics/mechanicsmanager.cpp index 33093c24d..7ed81f785 100644 --- a/apps/openmw/mwmechanics/mechanicsmanager.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanager.cpp @@ -250,6 +250,7 @@ namespace MWMechanics while (iter!=mActors.end()) if (iter->getCell()==cellStore) { + //std::cout << "Erasing an actor"; mActors.erase (iter++); } else diff --git a/apps/openmw/mwrender/actors.cpp b/apps/openmw/mwrender/actors.cpp new file mode 100644 index 000000000..3b94b19f7 --- /dev/null +++ b/apps/openmw/mwrender/actors.cpp @@ -0,0 +1,130 @@ +#include "actors.hpp" +#include + + + + +using namespace Ogre; +using namespace MWRender; +using namespace NifOgre; + +void Actors::setMwRoot(Ogre::SceneNode* root){ + mMwRoot = root; +} +void Actors::insertNPC(const MWWorld::Ptr& ptr){ + + insertBegin(ptr, true, true); + NpcAnimation* anim = new MWRender::NpcAnimation(ptr, mEnvironment, mRend); + + // + + mAllActors[ptr] = anim; + + +} +void Actors::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){ + Ogre::SceneNode* cellnode; + if(mCellSceneNodes.find(ptr.getCell()) == mCellSceneNodes.end()) + { + //Create the scenenode and put it in the map + cellnode = mMwRoot->createChildSceneNode(); + mCellSceneNodes[ptr.getCell()] = cellnode; + } + else + { + cellnode = mCellSceneNodes[ptr.getCell()]; + } + + Ogre::SceneNode* insert = cellnode->createChildSceneNode(); + const float *f = ptr.getRefData().getPosition().pos; + insert->setPosition(f[0], f[1], f[2]); + insert->setScale(ptr.getCellRef().scale, ptr.getCellRef().scale, ptr.getCellRef().scale); + + // Convert MW rotation to a quaternion: + f = ptr.getCellRef().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); + if (!enabled) + insert->setVisible (false); + ptr.getRefData().setBaseNode(insert); + + +} +void Actors::insertCreature (const MWWorld::Ptr& ptr){ + + insertBegin(ptr, true, true); + CreatureAnimation* anim = new MWRender::CreatureAnimation(ptr, mEnvironment, mRend); + //mAllActors.insert(std::pair(ptr,anim)); + mAllActors[ptr] = anim; + //mAllActors.push_back(&anim);*/ +} + +bool Actors::deleteObject (const MWWorld::Ptr& ptr) +{ + delete mAllActors[ptr]; + mAllActors.erase(ptr); + if (Ogre::SceneNode *base = ptr.getRefData().getBaseNode()) + { + + Ogre::SceneNode *parent = base->getParentSceneNode(); + + for (std::map::const_iterator iter ( + mCellSceneNodes.begin()); iter!=mCellSceneNodes.end(); ++iter) + if (iter->second==parent) + { + base->removeAndDestroyAllChildren(); + mRend.getScene()->destroySceneNode (base); + ptr.getRefData().setBaseNode (0); + return true; + } + + return false; + } + + return true; +} + +void Actors::removeCell(MWWorld::Ptr::CellStore* store){ + if(mCellSceneNodes.find(store) != mCellSceneNodes.end()) + { + Ogre::SceneNode* base = mCellSceneNodes[store]; + base->removeAndDestroyAllChildren(); + mCellSceneNodes.erase(store); + mRend.getScene()->destroySceneNode(base); + base = 0; + } + for(std::map::iterator iter = mAllActors.begin(); iter != mAllActors.end(); iter++) + { + if(iter->first.getCell() == store){ + delete iter->second; + mAllActors.erase(iter); + } + } + +} + +void Actors::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number){ + if(mAllActors.find(ptr) != mAllActors.end()) + mAllActors[ptr]->startScript(groupName, mode, number); +} +void Actors::skipAnimation (const MWWorld::Ptr& ptr){ + if(mAllActors.find(ptr) != mAllActors.end()) + mAllActors[ptr]->stopScript(); +} +void Actors::addTime(){ + //std::cout << "Adding time in actors\n"; + for(std::map::iterator iter = mAllActors.begin(); iter != mAllActors.end(); iter++) + { + (iter->second)->runAnimation(mEnvironment.mFrameDuration); + } +} diff --git a/apps/openmw/mwrender/actors.hpp b/apps/openmw/mwrender/actors.hpp new file mode 100644 index 000000000..93ec07f98 --- /dev/null +++ b/apps/openmw/mwrender/actors.hpp @@ -0,0 +1,59 @@ +#ifndef _GAME_RENDER_ACTORS_H +#define _GAME_RENDER_ACTORS_H + +#include "components/esm_store/cell_store.hpp" +#include +#include + + + +#include +#include "components/nifogre/ogre_nif_loader.hpp" + +#include "../mwworld/refdata.hpp" +#include "../mwworld/ptr.hpp" +#include "../mwworld/actiontalk.hpp" +#include "../mwworld/environment.hpp" +#include "npcanimation.hpp" +#include "creatureanimation.hpp" +#include + +namespace MWRender{ + class Actors{ + OEngine::Render::OgreRenderer &mRend; + std::map mCellSceneNodes; + Ogre::SceneNode* mMwRoot; + MWWorld::Environment& mEnvironment; + std::map mAllActors; + + + + public: + Actors(OEngine::Render::OgreRenderer& _rend, MWWorld::Environment& _env): mRend(_rend), mEnvironment(_env){} + ~Actors(){} + void setMwRoot(Ogre::SceneNode* root); + void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_); + void insertCreature (const MWWorld::Ptr& ptr); + void insertNPC(const MWWorld::Ptr& ptr); + bool deleteObject (const MWWorld::Ptr& ptr); + ///< \return found? + + void removeCell(MWWorld::Ptr::CellStore* store); + + void playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, + int number = 1); + ///< Run animation for a MW-reference. Calls to this function for references that are currently not + /// in the rendered scene should be ignored. + /// + /// \param mode: 0 normal, 1 immediate start, 2 immediate loop + /// \param number How offen the animation should be run + + void skipAnimation (const MWWorld::Ptr& ptr); + ///< Skip the animation for the given MW-reference for one frame. Calls to this function for + /// references that are currently not in the rendered scene should be ignored. + + void addTime(); + + }; +} +#endif \ No newline at end of file diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp new file mode 100644 index 000000000..5a9731d2d --- /dev/null +++ b/apps/openmw/mwrender/animation.cpp @@ -0,0 +1,568 @@ +#include "animation.hpp" + + +namespace MWRender{ + std::map Animation::mUniqueIDs; + + Animation::~Animation(){ + } + + std::string Animation::getUniqueID(std::string mesh){ + int counter; + std::string copy = mesh; + std::transform(copy.begin(), copy.end(), copy.begin(), ::tolower); + if(mUniqueIDs.find(copy) == mUniqueIDs.end()){ + counter = mUniqueIDs[copy] = 0; + } + else{ + mUniqueIDs[copy] = mUniqueIDs[copy] + 1; + counter = mUniqueIDs[copy]; + } + + std::stringstream out; + if(counter > 99 && counter < 1000) + out << "0"; + else if(counter > 9) + out << "00"; + else + out << "000"; + out << counter; + return out.str(); +} + void Animation::startScript(std::string groupname, int mode, int loops){ + //If groupname is recognized set animate to true + //Set the start time and stop time + //How many times to loop + if(groupname == "all"){ + animate = loops; + time = startTime; + } + else if(textmappings){ + + std::string startName = groupname + ": loop start"; + std::string stopName = groupname + ": loop stop"; + + bool first = false; + + if(loops > 1){ + startName = groupname + ": loop start"; + stopName = groupname + ": loop stop"; + + for(std::map::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++){ + + std::string current = iter->first.substr(0, startName.size()); + std::transform(current.begin(), current.end(), current.begin(), ::tolower); + std::string current2 = iter->first.substr(0, stopName.size()); + std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower); + + if(current == startName){ + startTime = iter->second; + animate = loops; + time = startTime; + first = true; + } + if(current2 == stopName){ + stopTime = iter->second; + if(first) + break; + } + } + } + if(!first){ + startName = groupname + ": start"; + stopName = groupname + ": stop"; + + for(std::map::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++){ + + std::string current = iter->first.substr(0, startName.size()); + std::transform(current.begin(), current.end(), current.begin(), ::tolower); + std::string current2 = iter->first.substr(0, stopName.size()); + std::transform(current2.begin(), current2.end(), current2.begin(), ::tolower); + + if(current == startName){ + startTime = iter->second; + animate = loops; + time = startTime; + first = true; + } + if(current2 == stopName){ + stopTime = iter->second; + if(first) + break; + } + } + } + + } + + } + void Animation::stopScript(){ + animate = 0; + } + + void Animation::handleShapes(std::vector* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel){ + bool useHandles = skel == creaturemodel->getSkeleton(); + shapeNumber = 0; + + std::vector::iterator allshapesiter; + for(allshapesiter = allshapes->begin(); allshapesiter != allshapes->end(); allshapesiter++) + + { + //std::map vecPosRot; + + Nif::NiTriShapeCopy& copy = *allshapesiter; + std::vector* allvertices = ©.vertices; + + //std::set vertices; + //std::set normals; + //std::vector boneinfovector = copy.boneinfo; + std::map >* verticesToChange = ©.vertsToWeights; + + //std::cout << "Name " << copy.sname << "\n"; + Ogre::HardwareVertexBufferSharedPtr vbuf = creaturemodel->getMesh()->getSubMesh(copy.sname)->vertexData->vertexBufferBinding->getBuffer(0); + Ogre::Real* pReal = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); + //Ogre::HardwareVertexBufferSharedPtr vbufNormal = creaturemodel->getMesh()->getSubMesh(copy.sname)->vertexData->vertexBufferBinding->getBuffer(1); + // Ogre::Real* pRealNormal = static_cast(vbufNormal->lock(Ogre::HardwareBuffer::HBL_NORMAL)); + + std::vector initialVertices = copy.morph.getInitialVertices(); + //Each shape has multiple indices + if(initialVertices.size() ) + { + + if(copy.vertices.size() == initialVertices.size()) + { + //Create if it doesn't already exist + if(shapeIndexI.size() == static_cast (shapeNumber)) + { + std::vector vec; + shapeIndexI.push_back(vec); + } + if(time >= copy.morph.getStartTime() && time <= copy.morph.getStopTime()){ + float x; + for (unsigned int i = 0; i < copy.morph.getAdditionalVertices().size(); i++){ + int j = 0; + if(shapeIndexI[shapeNumber].size() <= i) + shapeIndexI[shapeNumber].push_back(0); + + + if(timeIndex(time,copy.morph.getRelevantTimes()[i],(shapeIndexI[shapeNumber])[i], j, x)){ + int indexI = (shapeIndexI[shapeNumber])[i]; + std::vector relevantData = (copy.morph.getRelevantData()[i]); + float v1 = relevantData[indexI].x; + float v2 = relevantData[j].x; + float t = v1 + (v2 - v1) * x; + if ( t < 0 ) t = 0; + if ( t > 1 ) t = 1; + if( t != 0 && initialVertices.size() == copy.morph.getAdditionalVertices()[i].size()) + { + for (unsigned int v = 0; v < initialVertices.size(); v++){ + initialVertices[v] += ((copy.morph.getAdditionalVertices()[i])[v]) * t; + } + } + + } + + + + } + + allvertices = &initialVertices; + } + shapeNumber++; + } + } + + + if(verticesToChange->size() > 0){ + + for(std::map >::iterator iter = verticesToChange->begin(); + iter != verticesToChange->end(); iter++) + { + std::vector inds = iter->second; + int verIndex = iter->first; + Ogre::Vector3 currentVertex = (*allvertices)[verIndex]; + Nif::NiSkinData::BoneInfoCopy* boneinfocopy = &(allshapesiter->boneinfo[inds[0].boneinfocopyindex]); + Ogre::Bone *bonePtr = 0; + if(useHandles) + { + bonePtr = skel->getBone(boneinfocopy->bonehandle); + } + else + bonePtr = skel->getBone(boneinfocopy->bonename); + + Ogre::Vector3 vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; + Ogre::Quaternion vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; + + + /*if(vecPosRot.find(boneinfocopy->bonehandle) == vecPosRot.end()){ + vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; + vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; + + if(useHandles){ + PosAndRot both; + both.vecPos = vecPos; + both.vecRot = vecRot; + vecPosRot[boneinfocopy->bonehandle] = both; + } + } + else{ + PosAndRot both = vecPosRot[boneinfocopy->bonehandle]; + vecPos = both.vecPos; + vecRot = both.vecRot; + }*/ + + Ogre::Vector3 absVertPos = (vecPos + vecRot * currentVertex) * inds[0].weight; + + + for(std::size_t i = 1; i < inds.size(); i++){ + boneinfocopy = &(allshapesiter->boneinfo[inds[i].boneinfocopyindex]); + if(useHandles) + bonePtr = skel->getBone(boneinfocopy->bonehandle); + else + bonePtr = skel->getBone(boneinfocopy->bonename); + vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; + vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; + + /*if(vecPosRot.find(boneinfocopy->bonehandle) == vecPosRot.end()){ + vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; + vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; + + if(useHandles){ + PosAndRot both; + both.vecPos = vecPos; + both.vecRot = vecRot; + vecPosRot[boneinfocopy->bonehandle] = both; + } + } + else{ + PosAndRot both = vecPosRot[boneinfocopy->bonehandle]; + vecPos = both.vecPos; + vecRot = both.vecRot; + }*/ + + + absVertPos += (vecPos + vecRot * currentVertex) * inds[i].weight; + + } + Ogre::Real* addr = (pReal + 3 * verIndex); + *addr = absVertPos.x; + *(addr+1) = absVertPos.y; + *(addr+2) = absVertPos.z; + } + +#if 0 + for (unsigned int i = 0; i < boneinfovector.size(); i++) + { + Nif::NiSkinData::BoneInfoCopy boneinfo = boneinfovector[i]; + if(skel->hasBone(boneinfo.bonename)){ + Ogre::Bone *bonePtr = skel->getBone(boneinfo.bonename); + Ogre::Vector3 vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfo.trafo.trans; + Ogre::Quaternion vecRot = bonePtr->_getDerivedOrientation() * boneinfo.trafo.rotation; + + for (unsigned int j=0; j < boneinfo.weights.size(); j++) + { + unsigned int verIndex = boneinfo.weights[j].vertex; + if(vertices.find(verIndex) == vertices.end()) + { + Ogre::Vector3 absVertPos = vecPos + vecRot * allvertices[verIndex]; + absVertPos = absVertPos * boneinfo.weights[j].weight; + vertices.insert(verIndex); + Ogre::Real* addr = (pReal + 3 * verIndex); + *addr = absVertPos.x; + *(addr+1) = absVertPos.y; + *(addr+2) = absVertPos.z; + + + } + else + { + + Ogre::Vector3 absVertPos = vecPos + vecRot * allvertices[verIndex]; + absVertPos = absVertPos * boneinfo.weights[j].weight; + Ogre::Vector3 old = Ogre::Vector3(pReal + 3 * verIndex); + absVertPos = absVertPos + old; + Ogre::Real* addr = (pReal + 3 * verIndex); + *addr = absVertPos.x; + *(addr+1) = absVertPos.y; + *(addr+2) = absVertPos.z; + + //std::cout << "Vertex" << verIndex << "Weight: " << boneinfo.weights[i].weight << "was seen twice\n"; + + } + + if(normals.find(verIndex) == normals.end()) + { + Ogre::Vector3 absNormalsPos = vecRot * allnormals[verIndex]; + absNormalsPos = absNormalsPos * boneinfo.weights[j].weight; + normals.insert(verIndex); + Ogre::Real* addr = (pRealNormal + 3 * verIndex); + *addr = absNormalsPos.x; + *(addr+1) = absNormalsPos.y; + *(addr+2) = absNormalsPos.z; + } + else + { + Ogre::Vector3 absNormalsPos = vecRot * allnormals[verIndex]; + absNormalsPos = absNormalsPos * boneinfo.weights[j].weight; + Ogre::Vector3 old = Ogre::Vector3(pRealNormal + 3 * verIndex); + absNormalsPos = absNormalsPos + old; + + Ogre::Real* addr = (pRealNormal + 3 * verIndex); + *addr = absNormalsPos.x; + *(addr+1) = absNormalsPos.y; + *(addr+2) = absNormalsPos.z; + + } +#endif + //} + //} + + + //} //Comment out + + ; + } + else + { + //Ogre::Bone *bonePtr = creaturemodel->getSkeleton()->getBone(copy.bonename); + Ogre::Quaternion shaperot = copy.trafo.rotation; + Ogre::Vector3 shapetrans = copy.trafo.trans; + float shapescale = copy.trafo.scale; + std::vector boneSequence = copy.boneSequence; + std::vector::iterator boneSequenceIter = boneSequence.begin(); + Ogre::Vector3 transmult; + Ogre::Quaternion rotmult; + float scale; + if(skel->hasBone(*boneSequenceIter)){ + Ogre::Bone *bonePtr = skel->getBone(*boneSequenceIter); + + + + + transmult = bonePtr->getPosition(); + rotmult = bonePtr->getOrientation(); + scale = bonePtr->getScale().x; + boneSequenceIter++; + for(; boneSequenceIter != boneSequence.end(); boneSequenceIter++) + { + if(creaturemodel->getSkeleton()->hasBone(*boneSequenceIter)){ + Ogre::Bone *bonePtr = creaturemodel->getSkeleton()->getBone(*boneSequenceIter); + // Computes C = B + AxC*scale + transmult = transmult + rotmult * bonePtr->getPosition(); + rotmult = rotmult * bonePtr->getOrientation(); + scale = scale * bonePtr->getScale().x; + } + //std::cout << "Bone:" << *boneSequenceIter << " "; + } + transmult = transmult + rotmult * shapetrans; + rotmult = rotmult * shaperot; + scale = shapescale * scale; + + //std::cout << "Position: " << transmult << "Rotation: " << rotmult << "\n"; + } + else + { + transmult = shapetrans; + rotmult = shaperot; + scale = shapescale; + } + + + + + // Computes C = B + AxC*scale + // final_vector = old_vector + old_rotation*new_vector*old_scale/ + + for(unsigned int i = 0; i < allvertices->size(); i++){ + Ogre::Vector3 current = transmult + rotmult * (*allvertices)[i]; + Ogre::Real* addr = pReal + i * 3; + *addr = current.x; + *(addr+1) = current.y; + *(addr + 2) = current.z; + + }/* + for(int i = 0; i < allnormals.size(); i++){ + Ogre::Vector3 current =rotmult * allnormals[i]; + Ogre::Real* addr = pRealNormal + i * 3; + *addr = current.x; + *(addr+1) = current.y; + *(addr + 2) = current.z; + + }*/ + + } + vbuf->unlock(); + //vbufNormal->unlock(); + } + + } + bool Animation::timeIndex( float time, std::vector times, int & i, int & j, float & x ){ + int count; + if ( (count = times.size()) > 0 ) + { + if ( time <= times[0] ) + { + i = j = 0; + x = 0.0; + return true; + } + if ( time >= times[count - 1] ) + { + i = j = count - 1; + x = 0.0; + return true; + } + + if ( i < 0 || i >= count ) + i = 0; + + float tI = times[i]; + if ( time > tI ) + { + j = i + 1; + float tJ; + while ( time >= ( tJ = times[j]) ) + { + i = j++; + tI = tJ; + } + x = ( time - tI ) / ( tJ - tI ); + return true; + } + else if ( time < tI ) + { + j = i - 1; + float tJ; + while ( time <= ( tJ = times[j] ) ) + { + i = j--; + tI = tJ; + } + x = ( time - tI ) / ( tJ - tI ); + return true; + } + else + { + j = i; + x = 0.0; + return true; + } + } + else + return false; + +} + + void Animation::handleAnimationTransforms(){ + Ogre::SkeletonInstance* skel = base->getSkeleton(); + + + Ogre::Bone* b = skel->getRootBone(); + b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3)); //This is a trick + + skel->_updateTransforms(); + //skel->_notifyManualBonesDirty(); + + base->getAllAnimationStates()->_notifyDirty(); + //base->_updateAnimation(); + base->_notifyMoved(); + + for(unsigned int i = 0; i < entityparts.size(); i++){ + Ogre::SkeletonInstance* skel = entityparts[i]->getSkeleton(); + + Ogre::Bone* b = skel->getRootBone(); + b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3));//This is a trick + + skel->_updateTransforms(); + // skel->_notifyManualBonesDirty(); + + entityparts[i]->getAllAnimationStates()->_notifyDirty(); + //entityparts[i]->_updateAnimation(); + entityparts[i]->_notifyMoved(); + } + + std::vector::iterator iter; + int slot = 0; + if(transformations){ + for(iter = transformations->begin(); iter != transformations->end(); iter++){ + if(time < iter->getStartTime() || time < startTime || time > iter->getStopTime()) + { + slot++; + //iter++; + continue; + + } + + float x; + float x2; + + std::vector quats = iter->getQuat(); + + std::vector ttime = iter->gettTime(); + std::vector::iterator ttimeiter = ttime.begin(); + + std::vector rtime = iter->getrTime(); + int rindexJ = 0; + timeIndex(time, rtime, rindexI[slot], rindexJ, x2); + int tindexJ = 0; + + + std::vector translist1 = iter->getTranslist1(); + + timeIndex(time, ttime, tindexI[slot], tindexJ, x); + + //std::cout << "X: " << x << " X2: " << x2 << "\n"; + Ogre::Vector3 t; + Ogre::Quaternion r; + + bool bTrans = translist1.size() > 0; + if(bTrans){ + Ogre::Vector3 v1 = translist1[tindexI[slot]]; + Ogre::Vector3 v2 = translist1[tindexJ]; + t = (v1 + (v2 - v1) * x); + + } + + bool bQuats = quats.size() > 0; + if(bQuats){ + r = Ogre::Quaternion::Slerp(x2, quats[rindexI[slot]], quats[rindexJ], true); + //bone->setOrientation(r); + } + skel = base->getSkeleton(); + if(skel->hasBone(iter->getBonename())){ + Ogre::Bone* bone = skel->getBone(iter->getBonename()); + if(bTrans) + bone->setPosition(t); + if(bQuats) + bone->setOrientation(r); + + + + skel->_updateTransforms(); + //skel->_notifyManualBonesDirty(); + base->getAllAnimationStates()->_notifyDirty(); + //base->_updateAnimation(); + base->_notifyMoved(); + } + for(std::size_t i = 0; i < entityparts.size(); i++){ + skel = entityparts[i]->getSkeleton(); + if(skel->hasBone(iter->getBonename())){ + Ogre::Bone* bone = skel->getBone(iter->getBonename()); + if(bTrans) + bone->setPosition(t); + if(bQuats) + bone->setOrientation(r); + + skel->_updateTransforms(); + //skel->_notifyManualBonesDirty(); + entityparts[i]->getAllAnimationStates()->_notifyDirty(); + // entityparts[i]->_updateAnimation(); + entityparts[i]->_notifyMoved(); + } + } + slot++; + } +} +} + +} diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp new file mode 100644 index 000000000..15c25707c --- /dev/null +++ b/apps/openmw/mwrender/animation.hpp @@ -0,0 +1,71 @@ +#ifndef _GAME_RENDER_ANIMATION_H +#define _GAME_RENDER_ANIMATION_H +#include +#include +#include "../mwworld/refdata.hpp" +#include "../mwworld/ptr.hpp" +#include "../mwworld/actiontalk.hpp" +#include "../mwworld/environment.hpp" +#include +#include +#include + + + + +namespace MWRender{ + +struct PosAndRot{ + Ogre::Quaternion vecRot; + Ogre::Vector3 vecPos; +}; + +class Animation{ + + protected: + Ogre::SceneNode* insert; + OEngine::Render::OgreRenderer &mRend; + MWWorld::Environment& mEnvironment; + static std::map mUniqueIDs; + + + std::vector* > shapeparts; //All the NiTriShape data that we need for animating an npc + + float time; + float startTime; + float stopTime; + int animate; + //Represents a rotation index for each bone + std::vectorrindexI; + //Represents a translation index for each bone + std::vectortindexI; + + //Only shapes with morphing data will use a shape number + int shapeNumber; + std::vector > shapeIndexI; + + //Ogre::SkeletonInstance* skel; + std::vector* shapes; //All the NiTriShapeData for a creature + std::vector entityparts; + + + std::vector* transformations; + std::map* textmappings; + Ogre::Entity* base; + void handleShapes(std::vector* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel); + void handleAnimationTransforms(); + bool timeIndex( float time, std::vector times, int & i, int & j, float & x ); + std::string getUniqueID(std::string mesh); + + public: + Animation(MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend): mRend(_rend), mEnvironment(_env), animate(0){}; + virtual void runAnimation(float timepassed) = 0; + void startScript(std::string groupname, int mode, int loops); + void stopScript(); + + + ~Animation(); + +}; +} +#endif \ No newline at end of file diff --git a/apps/openmw/mwrender/cellimp.cpp b/apps/openmw/mwrender/cellimp.cpp deleted file mode 100644 index 887941f05..000000000 --- a/apps/openmw/mwrender/cellimp.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "cellimp.hpp" - -#include -#include -#include - -#include "../mwworld/class.hpp" -#include "../mwworld/ptr.hpp" - -using namespace MWRender; - -template -void insertCellRefList (CellRenderImp& cellRender, MWWorld::Environment& environment, - T& cellRefList, ESMS::CellStore &cell) -{ - if (!cellRefList.list.empty()) - { - const MWWorld::Class& class_ = - MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.list.begin(), &cell)); - - for (typename T::List::iterator it = cellRefList.list.begin(); - it != cellRefList.list.end(); it++) - { - if (it->mData.getCount() || it->mData.isEnabled()) - { - MWWorld::Ptr ptr (&*it, &cell); - - try - { - class_.insertObj (ptr, cellRender, environment); - class_.enable (ptr, environment); - } - catch (const std::exception& e) - { - std::string error ("error during rendering: "); - std::cerr << error + e.what() << std::endl; - } - } - } - } -} - -void CellRenderImp::insertCell(ESMS::CellStore &cell, - MWWorld::Environment& environment) -{ - // Loop through all references in the cell - insertCellRefList (*this, environment, cell.activators, cell); - insertCellRefList (*this, environment, cell.potions, cell); - insertCellRefList (*this, environment, cell.appas, cell); - insertCellRefList (*this, environment, cell.armors, cell); - insertCellRefList (*this, environment, cell.books, cell); - insertCellRefList (*this, environment, cell.clothes, cell); - insertCellRefList (*this, environment, cell.containers, cell); - insertCellRefList (*this, environment, cell.creatures, cell); - insertCellRefList (*this, environment, cell.doors, cell); - insertCellRefList (*this, environment, cell.ingreds, cell); - insertCellRefList (*this, environment, cell.creatureLists, cell); - insertCellRefList (*this, environment, cell.itemLists, cell); - insertCellRefList (*this, environment, cell.lights, cell); - insertCellRefList (*this, environment, cell.lockpicks, cell); - insertCellRefList (*this, environment, cell.miscItems, cell); - insertCellRefList (*this, environment, cell.npcs, cell); - insertCellRefList (*this, environment, cell.probes, cell); - insertCellRefList (*this, environment, cell.repairs, cell); - insertCellRefList (*this, environment, cell.statics, cell); - insertCellRefList (*this, environment, cell.weapons, cell); -} diff --git a/apps/openmw/mwrender/cellimp.hpp b/apps/openmw/mwrender/cellimp.hpp deleted file mode 100644 index c497b1d19..000000000 --- a/apps/openmw/mwrender/cellimp.hpp +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef _GAME_RENDER_CELLIMP_H -#define _GAME_RENDER_CELLIMP_H - -#include - -#include "components/esm_store/cell_store.hpp" - -#include "../mwworld/refdata.hpp" -#include - -namespace Ogre -{ - class SceneNode; - class Vector3; -} - -namespace ESM -{ - class CellRef; -} - -namespace MWWorld -{ - class Environment; -} -namespace MWRender -{ - /// Base class for cell render, that implements inserting references into a cell in a - /// cell type- and render-engine-independent way. - - class CellRenderImp - { - public: - CellRenderImp() {} - virtual ~CellRenderImp() {} - - /// start inserting a new reference. - virtual void insertBegin (ESM::CellRef& ref, MWWorld::RefData& refData, bool static_ = false) = 0; - - virtual void rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements) = 0; - /// insert a mesh related to the most recent insertBegin call. - virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst) = 0; - virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements) = 0; - virtual void insertMesh(const std::string &mesh) = 0; - - virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements) = 0; - - virtual void insertObjectPhysics() = 0; - - virtual void insertActorPhysics() = 0; - - /// insert a light related to the most recent insertBegin call. - virtual void insertLight(float r, float g, float b, float radius) = 0; - - /// finish inserting a new reference and return a handle to it. - virtual std::string insertEnd (bool Enable) = 0; - - void insertCell(ESMS::CellStore &cell, MWWorld::Environment& environment); - - }; - - /// Exception-safe rendering - class Rendering - { - CellRenderImp& mCellRender; - bool mEnd; - - // not implemented - Rendering (const Rendering&); - Rendering& operator= (const Rendering&); - - public: - - Rendering (CellRenderImp& cellRender, ESM::CellRef& ref, MWWorld::RefData& refData, bool static_ = false) - : mCellRender (cellRender), mEnd (false) - { - mCellRender.insertBegin (ref, refData, static_); - } - - ~Rendering() - { - if (!mEnd) - mCellRender.insertEnd (false); - } - - std::string end (bool enable) - { - assert (!mEnd); - mEnd = true; - return mCellRender.insertEnd (enable); - } - }; -} - -#endif diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp new file mode 100644 index 000000000..3cb40f2f1 --- /dev/null +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -0,0 +1,62 @@ +#include "creatureanimation.hpp" + +#include "../mwworld/world.hpp" + +using namespace Ogre; +using namespace NifOgre; +namespace MWRender{ + +CreatureAnimation::~CreatureAnimation(){ + +} +CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,OEngine::Render::OgreRenderer& _rend): Animation(_env,_rend){ + insert = ptr.getRefData().getBaseNode(); + ESMS::LiveCellRef *ref = + ptr.get(); + + assert (ref->base != NULL); + if(!ref->base->model.empty()){ + const std::string &mesh = "meshes\\" + ref->base->model; + std::string meshNumbered = mesh + getUniqueID(mesh) + ">|"; + NifOgre::NIFLoader::load(meshNumbered); + base = mRend.getScene()->createEntity(meshNumbered); + std::string meshZero = mesh + "0000>|"; + + if((transformations = (NIFLoader::getSingletonPtr())->getAnim(meshZero))){ + + for(std::size_t init = 0; init < transformations->size(); init++){ + rindexI.push_back(0); + tindexI.push_back(0); + } + stopTime = transformations->begin()->getStopTime(); + startTime = transformations->begin()->getStartTime(); + shapes = (NIFLoader::getSingletonPtr())->getShapes(meshZero); + } + textmappings = NIFLoader::getSingletonPtr()->getTextIndices(meshZero); + insert->attachObject(base); + } +} + +void CreatureAnimation::runAnimation(float timepassed){ + if(animate > 0){ + //Add the amount of time passed to time + + //Handle the animation transforms dependent on time + + //Handle the shapes dependent on animation transforms + time += timepassed; + if(time >= stopTime){ + animate--; + //std::cout << "Stopping the animation\n"; + if(animate == 0) + time = stopTime; + else + time = startTime + (time - stopTime); + } + + handleAnimationTransforms(); + handleShapes(shapes, base, base->getSkeleton()); + + } +} +} diff --git a/apps/openmw/mwrender/creatureanimation.hpp b/apps/openmw/mwrender/creatureanimation.hpp new file mode 100644 index 000000000..179991442 --- /dev/null +++ b/apps/openmw/mwrender/creatureanimation.hpp @@ -0,0 +1,26 @@ +#ifndef _GAME_RENDER_CREATUREANIMATION_H +#define _GAME_RENDER_CREATUREANIMATION_H + +#include "animation.hpp" +#include + + +#include "../mwworld/refdata.hpp" +#include "../mwworld/ptr.hpp" +#include "../mwworld/environment.hpp" +#include "components/nifogre/ogre_nif_loader.hpp" + + +namespace MWRender{ + +class CreatureAnimation: public Animation{ + + public: + ~CreatureAnimation(); + CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend); + virtual void runAnimation(float timepassed); + + +}; +} +#endif \ No newline at end of file diff --git a/apps/openmw/mwrender/debugging.cpp b/apps/openmw/mwrender/debugging.cpp new file mode 100644 index 000000000..60b299acd --- /dev/null +++ b/apps/openmw/mwrender/debugging.cpp @@ -0,0 +1,38 @@ +#include "debugging.hpp" + +#include + +#include "OgreRoot.h" +#include "OgreRenderWindow.h" +#include "OgreSceneManager.h" +#include "OgreViewport.h" +#include "OgreCamera.h" +#include "OgreTextureManager.h" + +#include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone +#include "../mwworld/ptr.hpp" +#include + +#include "player.hpp" + +using namespace MWRender; +using namespace Ogre; + +Debugging::Debugging(OEngine::Physic::PhysicEngine* engine){ + eng = engine; +} + + +bool Debugging::toggleRenderMode (int mode){ + switch (mode) + { + case MWWorld::World::Render_CollisionDebug: + + // TODO use a proper function instead of accessing the member variable + // directly. + eng->setDebugRenderingMode (!eng->isDebugCreated); + return eng->isDebugCreated; + } + + return false; +} diff --git a/apps/openmw/mwrender/debugging.hpp b/apps/openmw/mwrender/debugging.hpp new file mode 100644 index 000000000..b48cfaee2 --- /dev/null +++ b/apps/openmw/mwrender/debugging.hpp @@ -0,0 +1,43 @@ +#ifndef _GAME_RENDER_MWSCENE_H +#define _GAME_RENDER_MWSCENE_H + +#include +#include +#include + +#include +#include + +namespace Ogre +{ + class Camera; + class Viewport; + class SceneManager; + class SceneNode; + class RaySceneQuery; + class Quaternion; + class Vector3; +} + +namespace MWWorld +{ + class World; +} + +namespace MWRender +{ + class Player; + + class Debugging{ + OEngine::Physic::PhysicEngine* eng; + + + public: + Debugging(OEngine::Physic::PhysicEngine* engine); + bool toggleRenderMode (int mode); + }; + + +} + +#endif diff --git a/apps/openmw/mwrender/exterior.cpp b/apps/openmw/mwrender/exterior.cpp deleted file mode 100644 index aa8ca0a3c..000000000 --- a/apps/openmw/mwrender/exterior.cpp +++ /dev/null @@ -1,454 +0,0 @@ -#include "exterior.hpp" - -#include -#include -#include -#include -#include - -#include -#include "mwscene.hpp" -#include -#include "mwscene.hpp" -#include - -using namespace MWRender; -using namespace Ogre; -using namespace ESMS; - -bool ExteriorCellRender::lightConst = false; -float ExteriorCellRender::lightConstValue = 0.0f; - -bool ExteriorCellRender::lightLinear = true; -int ExteriorCellRender::lightLinearMethod = 1; -float ExteriorCellRender::lightLinearValue = 3; -float ExteriorCellRender::lightLinearRadiusMult = 1; - -bool ExteriorCellRender::lightQuadratic = false; -int ExteriorCellRender::lightQuadraticMethod = 2; -float ExteriorCellRender::lightQuadraticValue = 16; -float ExteriorCellRender::lightQuadraticRadiusMult = 1; - -bool ExteriorCellRender::lightOutQuadInLin = false; - -int ExteriorCellRender::uniqueID = 0; - -ExteriorCellRender::ExteriorCellRender(ESMS::CellStore &_cell, MWWorld::Environment& environment, - MWScene &_scene, MWWorld::PhysicsSystem *physics) - : mCell(_cell), mEnvironment (environment), mScene(_scene), mPhysics(physics), mBase(NULL), mInsert(NULL), mAmbientMode (0) -{ - uniqueID = uniqueID +1; - sg = mScene.getMgr()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); -} - - - -void ExteriorCellRender::insertBegin (ESM::CellRef &ref, MWWorld::RefData& refData, bool static_) -{ - assert (!mInsert); - - isStatic = static_; - - // Create and place scene node for this object - mInsert = mBase->createChildSceneNode(); - - const float *f = ref.pos.pos; - mInsert->setPosition(f[0], f[1], f[2]); - mInsert->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 - mInsert->setOrientation(xr*yr*zr); - - mInsertMesh.clear(); -} - - -void ExteriorCellRender::rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements) -{ - assert(mInsert); - Ogre::SceneNode *parent = mInsert; - //std::cout << "ELEMENTS:" << elements; - for (int i = 0; i < elements; i++){ - if(sceneNodeName[i] != "" && parent->getChild(sceneNodeName[i])) - parent = dynamic_cast (parent->getChild(sceneNodeName[i])); - } - parent->rotate(axis, angle); -} -/* -void ExteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements){ - assert (mInsert); - //mInsert-> - Ogre::SceneNode *parent = mInsert; - for (int i = 0; i < elements; i++){ - if(sceneParent[i] != "" && parent->getChild(sceneParent[i])) - parent = dynamic_cast (parent->getChild(sceneParent[i])); - } - - mNpcPart = parent->createChildSceneNode(sceneNodeName); - NIFLoader::load(mesh); - MovableObject *ent = mScene.getMgr()->createEntity(mesh); - - mNpcPart->translate(vec); - mNpcPart->rotate(axis, angle); - // mNpcPart->translate(vec); - //mNpcPart->rotate(axis, angle); - mNpcPart->attachObject(ent); - //mNpcPart-> - -} -*/ -void ExteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements) -{ - insertMesh(mesh, vec, axis, angle, sceneNodeName, sceneParent, elements, true); -} -void ExteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst){ - - assert (mInsert); - //mInsert-> - Ogre::SceneNode *parent = mInsert; - for (int i = 0; i < elements; i++){ - if(sceneParent[i] != "" && parent->getChild(sceneParent[i])) - parent = dynamic_cast (parent->getChild(sceneParent[i])); - } - - mNpcPart = parent->createChildSceneNode(sceneNodeName); - MeshPtr good2 = NifOgre::NIFLoader::load(mesh); - - MovableObject *ent = mScene.getMgr()->createEntity(mesh); - - - if(translateFirst){ - mNpcPart->translate(vec); - mNpcPart->rotate(axis, angle); - } - else{ - - mNpcPart->rotate(axis, angle); - mNpcPart->translate(vec); - } - mNpcPart->attachObject(ent); - - Ogre::MeshManager *m = MeshManager::getSingletonPtr(); - const std::string beast1 ="meshes\\b\\B_N_Khajiit_F_Skins.nif"; - const std::string beast2 ="meshes\\b\\B_N_Khajiit_M_Skins.nif"; - const std::string beast3 ="meshes\\b\\B_N_Argonian_F_Skins.nif"; - const std::string beast4 ="meshes\\b\\B_N_Argonian_M_Skins.nif"; - - const std::string beasttail1 ="tail\\b\\B_N_Khajiit_F_Skins.nif"; - const std::string beasttail2 ="tail\\b\\B_N_Khajiit_M_Skins.nif"; - const std::string beasttail3 ="tail\\b\\B_N_Argonian_F_Skins.nif"; - const std::string beasttail4 ="tail\\b\\B_N_Argonian_M_Skins.nif"; - - const std::string beastfoot1 ="foot\\b\\B_N_Khajiit_F_Skins.nif"; - const std::string beastfoot2 ="foot\\b\\B_N_Khajiit_M_Skins.nif"; - const std::string beastfoot3 ="foot\\b\\B_N_Argonian_F_Skins.nif"; - const std::string beastfoot4 ="foot\\b\\B_N_Argonian_M_Skins.nif"; - if(mesh.compare(beast1) == 0 && m->getByName(beasttail1).isNull()) - { - //std::cout << "CLONINGKHAJIITF\n"; - good2->reload(); - MeshPtr tail = good2->clone(beasttail1); - good2->reload(); - MeshPtr foot = good2->clone(beastfoot1); - good2->reload(); - } - else if(mesh.compare(beast2) == 0 && m->getByName(beasttail2).isNull()) - { - //std::cout << "CLONINGKHAJIITM\n"; - good2->reload(); - MeshPtr tail = good2->clone(beasttail2); - good2->reload(); - MeshPtr foot = good2->clone(beastfoot2); - good2->reload(); - } - else if(mesh.compare(beast3) == 0 && m->getByName(beasttail3).isNull()) - { - //std::cout << "CLONINGARGONIANF\n"; - good2->reload(); - MeshPtr tail = good2->clone(beasttail3); - good2->reload(); - MeshPtr foot = good2->clone(beastfoot3); - good2->reload(); - } - else if(mesh.compare(beast4) == 0 && m->getByName(beasttail4).isNull()) - { - //std::cout << "CLONINGARGONIANM\n"; - good2->reload(); - MeshPtr tail = good2->clone(beasttail4); - good2->reload(); - MeshPtr foot = good2->clone(beastfoot4); - good2->reload(); - } -} -// insert a mesh related to the most recent insertBegin call. - -void ExteriorCellRender::scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements) -{ - assert(mInsert); - Ogre::SceneNode *parent = mInsert; - //std::cout << "ELEMENTS:" << elements; - for (int i = 0; i < elements; i++){ - if(sceneNodeName[i] != "" && parent->getChild(sceneNodeName[i])) - parent = dynamic_cast (parent->getChild(sceneNodeName[i])); - } - parent->scale(axis); -} - -// insert a mesh related to the most recent insertBegin call. - - -void ExteriorCellRender::insertMesh(const std::string &mesh) -{ - assert (mInsert); - - NifOgre::NIFLoader::load(mesh); - Entity *ent = mScene.getMgr()->createEntity(mesh); - - if(!isStatic) - { - mInsert->attachObject(ent); - } - else - { - sg->addEntity(ent,mInsert->_getDerivedPosition(),mInsert->_getDerivedOrientation(),mInsert->_getDerivedScale()); - sg->setRegionDimensions(Ogre::Vector3(100000,10000,100000)); - mScene.getMgr()->destroyEntity(ent); - } - if (mInsertMesh.empty()) - mInsertMesh = mesh; -} - -void ExteriorCellRender::insertObjectPhysics() -{ - if (!mInsertMesh.empty()) - { - mPhysics->addObject (mInsert->getName(), mInsertMesh, mInsert->getOrientation(), - mInsert->getScale().x, mInsert->getPosition()); - } -} - -void ExteriorCellRender::insertActorPhysics() -{ - mPhysics->addActor (mInsert->getName(), mInsertMesh, mInsert->getPosition()); -} - -// insert a light related to the most recent insertBegin call. -void ExteriorCellRender::insertLight(float r, float g, float b, float radius) -{ - assert (mInsert); - - Ogre::Light *light = mScene.getMgr()->createLight(); - light->setDiffuseColour (r, g, b); - - float cval=0.0f, lval=0.0f, qval=0.0f; - - if(lightConst) - cval = lightConstValue; - if(!lightOutQuadInLin) - { - if(lightLinear) - radius *= lightLinearRadiusMult; - if(lightQuadratic) - radius *= lightQuadraticRadiusMult; - - if(lightLinear) - lval = lightLinearValue / pow(radius, lightLinearMethod); - if(lightQuadratic) - qval = lightQuadraticValue / pow(radius, lightQuadraticMethod); - } - else - { - // FIXME: - // Do quadratic or linear, depending if we're in an exterior or interior - // cell, respectively. Ignore lightLinear and lightQuadratic. - } - - light->setAttenuation(10*radius, cval, lval, qval); - - mInsert->attachObject(light); -} - -// finish inserting a new reference and return a handle to it. - -std::string ExteriorCellRender::insertEnd (bool enable) -{ - assert (mInsert); - - std::string handle = mInsert->getName(); - - if (!enable) - mInsert->setVisible (false); - - mInsert = 0; - - return handle; -} - -// configure lighting according to cell - -void ExteriorCellRender::configureAmbient() -{ - mAmbientColor.setAsABGR (mCell.cell->ambi.ambient); - setAmbientMode(); - - // Create a "sun" that shines light downwards. It doesn't look - // completely right, but leave it for now. - Ogre::Light *light = mScene.getMgr()->createLight(); - Ogre::ColourValue colour; - colour.setAsABGR (mCell.cell->ambi.sunlight); - light->setDiffuseColour (colour); - light->setType(Ogre::Light::LT_DIRECTIONAL); - light->setDirection(0,-1,0); -} - -// configure fog according to cell -void ExteriorCellRender::configureFog() -{ - Ogre::ColourValue color; - color.setAsABGR (mCell.cell->ambi.fog); - - float high = 4500 + 9000 * (1-mCell.cell->ambi.fogDensity); - float low = 200; - - mScene.getMgr()->setFog (FOG_LINEAR, color, 0, low, high); - mScene.getCamera()->setFarClipDistance (high + 10); - mScene.getViewport()->setBackgroundColour (color); -} - -void ExteriorCellRender::setAmbientMode() -{ - switch (mAmbientMode) - { - case 0: - - mScene.getMgr()->setAmbientLight(mAmbientColor); - break; - - case 1: - - mScene.getMgr()->setAmbientLight(0.7f*mAmbientColor + 0.3f*ColourValue(1,1,1)); - break; - - case 2: - - mScene.getMgr()->setAmbientLight(ColourValue(1,1,1)); - break; - } -} - -void ExteriorCellRender::show() -{ - // FIXME: this one may be the bug - mBase = mScene.getRoot()->createChildSceneNode(); - - configureAmbient(); - configureFog(); - - insertCell(mCell, mEnvironment); - - sg->build(); -} - -void ExteriorCellRender::hide() -{ - if(mBase) - mBase->setVisible(false); -} - -void ExteriorCellRender::destroyAllAttachedMovableObjects(Ogre::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(itObject.getNext()); - i_pSceneNode->getCreator()->destroyMovableObject( pObject ); - } - - // Recurse to child SceneNodes - SceneNode::ChildNodeIterator itChild = i_pSceneNode->getChildIterator(); - - while ( itChild.hasMoreElements() ) - { - SceneNode* pChildNode = static_cast(itChild.getNext()); - destroyAllAttachedMovableObjects( pChildNode ); - } -} - -void ExteriorCellRender::destroy() -{ - if(mBase) - { - destroyAllAttachedMovableObjects(mBase); - mBase->removeAndDestroyAllChildren(); - mScene.getMgr()->destroySceneNode(mBase); - } - - mBase = 0; - - if (sg) - { - mScene.getMgr()->destroyStaticGeometry (sg); - sg = 0; - } -} - -// Switch through lighting modes. - -void ExteriorCellRender::toggleLight() -{ - if (mAmbientMode==2) - mAmbientMode = 0; - else - ++mAmbientMode; - - switch (mAmbientMode) - { - case 0: std::cout << "Setting lights to normal\n"; break; - case 1: std::cout << "Turning the lights up\n"; break; - case 2: std::cout << "Turning the lights to full\n"; break; - } - - setAmbientMode(); -} - -void ExteriorCellRender::enable (const std::string& handle) -{ - if (!handle.empty()) - mScene.getMgr()->getSceneNode (handle)->setVisible (true); -} - -void ExteriorCellRender::disable (const std::string& handle) -{ - if (!handle.empty()) - mScene.getMgr()->getSceneNode (handle)->setVisible (false); -} - -void ExteriorCellRender::deleteObject (const std::string& handle) -{ - if (!handle.empty()) - { - Ogre::SceneNode *node = mScene.getMgr()->getSceneNode (handle); - node->removeAndDestroyAllChildren(); - mScene.getMgr()->destroySceneNode (node); - } -} diff --git a/apps/openmw/mwrender/exterior.hpp b/apps/openmw/mwrender/exterior.hpp deleted file mode 100644 index 24464698f..000000000 --- a/apps/openmw/mwrender/exterior.hpp +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef _GAME_RENDER_EXTERIOR_H -#define _GAME_RENDER_EXTERIOR_H - -#include "cell.hpp" -#include "cellimp.hpp" -#include "../mwworld/physicssystem.hpp" - -#include "OgreColourValue.h" -#include -#include - -namespace Ogre -{ - class SceneNode; -} - -namespace MWWorld -{ - class Environment; -} - -namespace MWRender -{ - class MWScene; - - /** - This class is responsible for inserting meshes and other - rendering objects from the given cell into the given rendering - scene. - */ - - class ExteriorCellRender : public CellRender, private CellRenderImp - { - - static bool lightConst; - static float lightConstValue; - - static bool lightLinear; - static int lightLinearMethod; - static float lightLinearValue; - static float lightLinearRadiusMult; - - static bool lightQuadratic; - static int lightQuadraticMethod; - static float lightQuadraticValue; - static float lightQuadraticRadiusMult; - - static bool lightOutQuadInLin; - - ESMS::CellStore &mCell; - MWWorld::Environment &mEnvironment; - MWScene &mScene; - MWWorld::PhysicsSystem *mPhysics; - - /// The scene node that contains all objects belonging to this - /// cell. - Ogre::SceneNode *mBase; - - Ogre::SceneNode *mInsert; - std::string mInsertMesh; - Ogre::SceneNode *mNpcPart; - - //the static geometry - Ogre::StaticGeometry *sg; - bool isStatic; - - // 0 normal, 1 more bright, 2 max - int mAmbientMode; - - Ogre::ColourValue mAmbientColor; - - /// start inserting a new reference. - virtual void insertBegin (ESM::CellRef &ref, MWWorld::RefData& refData, bool static_ = false); - - /// insert a mesh related to the most recent insertBegin call. - virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements); - virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst); - - virtual void insertMesh(const std::string &mesh); - - virtual void rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements); - virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements); - - virtual void insertObjectPhysics(); - - virtual void insertActorPhysics(); - - /// insert a light related to the most recent insertBegin call. - virtual void insertLight(float r, float g, float b, float radius); - - /// finish inserting a new reference and return a handle to it. - virtual std::string insertEnd (bool Enable); - - /// configure lighting according to cell - void configureAmbient(); - - /// configure fog according to cell - void configureFog(); - - void setAmbientMode(); - - - public: - - ExteriorCellRender(ESMS::CellStore &_cell, MWWorld::Environment& environment, - MWScene &_scene, MWWorld::PhysicsSystem *physics); - - virtual ~ExteriorCellRender() { destroy(); } - - /// Make the cell visible. Load the cell if necessary. - virtual void show(); - - /// Remove the cell from rendering, but don't remove it from - /// memory. - virtual void hide(); - - /// Destroy all rendering objects connected with this cell. - virtual void destroy(); // comment by Zini: shouldn't this go into the destructor? - - /// Switch through lighting modes. - void toggleLight(); - - /// Make the reference with the given handle visible. - virtual void enable (const std::string& handle); - - /// Make the reference with the given handle invisible. - virtual void disable (const std::string& handle); - - /// Remove the reference with the given handle permanently from the scene. - virtual void deleteObject (const std::string& handle); - - void destroyAllAttachedMovableObjects(Ogre::SceneNode* i_pSceneNode); - - static int uniqueID; - }; -} - -#endif diff --git a/apps/openmw/mwrender/interior.cpp b/apps/openmw/mwrender/interior.cpp deleted file mode 100644 index 99843272f..000000000 --- a/apps/openmw/mwrender/interior.cpp +++ /dev/null @@ -1,409 +0,0 @@ -#include "interior.hpp" - -#include -#include -#include -#include -#include -#include - -#include -#include "mwscene.hpp" -#include -#include - -#include - -using namespace MWRender; -using namespace Ogre; -using namespace ESMS; - -bool InteriorCellRender::lightConst = false; -float InteriorCellRender::lightConstValue = 0.0f; - -bool InteriorCellRender::lightLinear = true; -int InteriorCellRender::lightLinearMethod = 1; -float InteriorCellRender::lightLinearValue = 3; -float InteriorCellRender::lightLinearRadiusMult = 1; - -bool InteriorCellRender::lightQuadratic = false; -int InteriorCellRender::lightQuadraticMethod = 2; -float InteriorCellRender::lightQuadraticValue = 16; -float InteriorCellRender::lightQuadraticRadiusMult = 1; - -bool InteriorCellRender::lightOutQuadInLin = false; - -// start inserting a new reference. - -void InteriorCellRender::insertBegin (ESM::CellRef &ref, MWWorld::RefData& refData, bool static_) -{ - assert (!insert); - - // Create and place scene node for this object - insert = base->createChildSceneNode(); - - const float *f = refData.getPosition().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); - - mInsertMesh.clear(); -} - -// insert a mesh related to the most recent insertBegin call. -void InteriorCellRender::rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements) -{ - assert(insert); - Ogre::SceneNode *parent = insert; - //std::cout << "ELEMENTS:" << elements; - for (int i = 0; i < elements; i++){ - if(sceneNodeName[i] != "" && parent->getChild(sceneNodeName[i])) - parent = dynamic_cast (parent->getChild(sceneNodeName[i])); - } - parent->rotate(axis, angle); -} -// insert a mesh related to the most recent insertBegin call. - -void InteriorCellRender::scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements) -{ - assert(insert); - Ogre::SceneNode *parent = insert; - //std::cout << "ELEMENTS:" << elements; - for (int i = 0; i < elements; i++){ - if(sceneNodeName[i] != "" && parent->getChild(sceneNodeName[i])) - parent = dynamic_cast (parent->getChild(sceneNodeName[i])); - } - parent->scale(axis); -} -void InteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements) -{ - insertMesh(mesh, vec, axis, angle, sceneNodeName, sceneParent, elements, true); -} -void InteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst){ - - assert (insert); - //insert-> - Ogre::SceneNode *parent = insert; - for (int i = 0; i < elements; i++){ - if(sceneParent[i] != "" && parent->getChild(sceneParent[i])) - parent = dynamic_cast (parent->getChild(sceneParent[i])); - } - - npcPart = parent->createChildSceneNode(sceneNodeName); - //npcPart->showBoundingBox(true); - - MeshPtr good2 = NifOgre::NIFLoader::load(mesh); - - MovableObject *ent = scene.getMgr()->createEntity(mesh); - //ent->extr - - // MovableObject *ent2 = scene.getMgr()->createEntity(bounds - // ); - //ent-> - //std::cout << mesh << bounds << "\n"; - - if(translateFirst){ - npcPart->translate(vec); - npcPart->rotate(axis, angle); - } - else{ - - npcPart->rotate(axis, angle); - npcPart->translate(vec); - } - - npcPart->attachObject(ent); - Ogre::MeshManager *m = MeshManager::getSingletonPtr(); - const std::string beast1 ="meshes\\b\\B_N_Khajiit_F_Skins.nif"; - const std::string beast2 ="meshes\\b\\B_N_Khajiit_M_Skins.nif"; - const std::string beast3 ="meshes\\b\\B_N_Argonian_F_Skins.nif"; - const std::string beast4 ="meshes\\b\\B_N_Argonian_M_Skins.nif"; - - const std::string beasttail1 ="tail\\b\\B_N_Khajiit_F_Skins.nif"; - const std::string beasttail2 ="tail\\b\\B_N_Khajiit_M_Skins.nif"; - const std::string beasttail3 ="tail\\b\\B_N_Argonian_F_Skins.nif"; - const std::string beasttail4 ="tail\\b\\B_N_Argonian_M_Skins.nif"; - - const std::string beastfoot1 ="foot\\b\\B_N_Khajiit_F_Skins.nif"; - const std::string beastfoot2 ="foot\\b\\B_N_Khajiit_M_Skins.nif"; - const std::string beastfoot3 ="foot\\b\\B_N_Argonian_F_Skins.nif"; - const std::string beastfoot4 ="foot\\b\\B_N_Argonian_M_Skins.nif"; - if(mesh.compare(beast1) == 0 && m->getByName(beasttail1).isNull()) - { - //std::cout << "CLONINGKHAJIITF\n"; - good2->reload(); - MeshPtr tail = good2->clone(beasttail1); - good2->reload(); - MeshPtr foot = good2->clone(beastfoot1); - good2->reload(); - } - else if(mesh.compare(beast2) == 0 && m->getByName(beasttail2).isNull()) - { - //std::cout << "CLONINGKHAJIITM\n"; - good2->reload(); - MeshPtr tail = good2->clone(beasttail2); - good2->reload(); - MeshPtr foot = good2->clone(beastfoot2); - good2->reload(); - } - else if(mesh.compare(beast3) == 0 && m->getByName(beasttail3).isNull()) - { - //std::cout << "CLONINGARGONIANF\n"; - good2->reload(); - MeshPtr tail = good2->clone(beasttail3); - good2->reload(); - MeshPtr foot = good2->clone(beastfoot3); - good2->reload(); - } - else if(mesh.compare(beast4) == 0 && m->getByName(beasttail4).isNull()) - { - //std::cout << "CLONINGARGONIANM\n"; - good2->reload(); - MeshPtr tail = good2->clone(beasttail4); - good2->reload(); - MeshPtr foot = good2->clone(beastfoot4); - good2->reload(); - } -} - -void InteriorCellRender::insertMesh(const std::string &mesh) -{ - assert (insert); - - NifOgre::NIFLoader::load(mesh); - MovableObject *ent = scene.getMgr()->createEntity(mesh); - insert->attachObject(ent); - - if (mInsertMesh.empty()) - mInsertMesh = mesh; -} - -void InteriorCellRender::insertObjectPhysics() -{ - if (!mInsertMesh.empty()) - { - mPhysics->addObject (insert->getName(), mInsertMesh, insert->getOrientation(), - insert->getScale().x, insert->getPosition()); - } -} - -void InteriorCellRender::insertActorPhysics() -{ - mPhysics->addActor (insert->getName(), mInsertMesh, insert->getPosition()); -} - -// insert a light related to the most recent insertBegin call. -void InteriorCellRender::insertLight(float r, float g, float b, float radius) -{ - assert (insert); - - Ogre::Light *light = scene.getMgr()->createLight(); - light->setDiffuseColour (r, g, b); - - float cval=0.0f, lval=0.0f, qval=0.0f; - - if(lightConst) - cval = lightConstValue; - if(!lightOutQuadInLin) - { - if(lightLinear) - radius *= lightLinearRadiusMult; - if(lightQuadratic) - radius *= lightQuadraticRadiusMult; - - if(lightLinear) - lval = lightLinearValue / pow(radius, lightLinearMethod); - if(lightQuadratic) - qval = lightQuadraticValue / pow(radius, lightQuadraticMethod); - } - else - { - // FIXME: - // Do quadratic or linear, depending if we're in an exterior or interior - // cell, respectively. Ignore lightLinear and lightQuadratic. - } - - light->setAttenuation(10*radius, cval, lval, qval); - - insert->attachObject(light); -} - -// finish inserting a new reference and return a handle to it. - -std::string InteriorCellRender::insertEnd (bool enable) -{ - assert (insert); - - std::string handle = insert->getName(); - - if (!enable) - insert->setVisible (false); - - insert = 0; - - return handle; -} - -// configure lighting according to cell - -void InteriorCellRender::configureAmbient() -{ - ambientColor.setAsABGR (cell.cell->ambi.ambient); - setAmbientMode(); - - // Create a "sun" that shines light downwards. It doesn't look - // completely right, but leave it for now. - Ogre::Light *light = scene.getMgr()->createLight(); - Ogre::ColourValue colour; - colour.setAsABGR (cell.cell->ambi.sunlight); - light->setDiffuseColour (colour); - light->setType(Ogre::Light::LT_DIRECTIONAL); - light->setDirection(0,-1,0); -} - -// configure fog according to cell -void InteriorCellRender::configureFog() -{ - Ogre::ColourValue color; - color.setAsABGR (cell.cell->ambi.fog); - - float high = 4500 + 9000 * (1-cell.cell->ambi.fogDensity); - float low = 200; - - scene.getMgr()->setFog (FOG_LINEAR, color, 0, low, high); - scene.getCamera()->setFarClipDistance (high + 10); - scene.getViewport()->setBackgroundColour (color); -} - -void InteriorCellRender::setAmbientMode() -{ - switch (ambientMode) - { - case 0: - - scene.getMgr()->setAmbientLight(ambientColor); - break; - - case 1: - - scene.getMgr()->setAmbientLight(0.7f*ambientColor + 0.3f*ColourValue(1,1,1)); - break; - - case 2: - - scene.getMgr()->setAmbientLight(ColourValue(1,1,1)); - break; - } -} - -void InteriorCellRender::show() -{ - base = scene.getRoot()->createChildSceneNode(); - - configureAmbient(); - configureFog(); - - insertCell(cell, mEnvironment); -} - -void InteriorCellRender::hide() -{ - if(base) - base->setVisible(false); -} - -void InteriorCellRender::destroy() -{ - if(base) - { - base->removeAndDestroyAllChildren(); - scene.getMgr()->destroySceneNode(base); - } - - base = NULL; -} - -// Switch through lighting modes. - -void InteriorCellRender::toggleLight() -{ - if (ambientMode==2) - ambientMode = 0; - else - ++ambientMode; - - switch (ambientMode) - { - case 0: std::cout << "Setting lights to normal\n"; break; - case 1: std::cout << "Turning the lights up\n"; break; - case 2: std::cout << "Turning the lights to full\n"; break; - } - - setAmbientMode(); -} - -void InteriorCellRender::enable (const std::string& handle) -{ - if (!handle.empty()) - scene.getMgr()->getSceneNode (handle)->setVisible (true); -} - -void InteriorCellRender::disable (const std::string& handle) -{ - if (!handle.empty()) - scene.getMgr()->getSceneNode (handle)->setVisible (false); -} - -void InteriorCellRender::deleteObject (const std::string& handle) -{ - if (!handle.empty()) - { - Ogre::SceneNode *node = scene.getMgr()->getSceneNode (handle); - node->removeAndDestroyAllChildren(); - scene.getMgr()->destroySceneNode (node); - } -} - -// 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(itObject.getNext()); - i_pSceneNode->getCreator()->destroyMovableObject( pObject ); - } - - // Recurse to child SceneNodes - SceneNode::ChildNodeIterator itChild = i_pSceneNode->getChildIterator(); - - while ( itChild.hasMoreElements() ) - { - SceneNode* pChildNode = static_cast(itChild.getNext()); - DestroyAllAttachedMovableObjects( pChildNode ); - } -} -*/ diff --git a/apps/openmw/mwrender/interior.hpp b/apps/openmw/mwrender/interior.hpp deleted file mode 100644 index cc1b5661d..000000000 --- a/apps/openmw/mwrender/interior.hpp +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef _GAME_RENDER_INTERIOR_H -#define _GAME_RENDER_INTERIOR_H - -#include "cell.hpp" -#include "cellimp.hpp" -#include "../mwworld/physicssystem.hpp" - -#include "OgreColourValue.h" -#include - -namespace Ogre -{ - class SceneNode; -} - -namespace MWWorld -{ - class Environment; -} - -namespace MWRender -{ - class MWScene; - - /** - This class is responsible for inserting meshes and other - rendering objects from the given cell into the given rendering - scene. - */ - - class InteriorCellRender : public CellRender, private CellRenderImp - { - //static bool isChest; - static bool lightConst; - static float lightConstValue; - - static bool lightLinear; - static int lightLinearMethod; - static float lightLinearValue; - static float lightLinearRadiusMult; - - static bool lightQuadratic; - static int lightQuadraticMethod; - static float lightQuadraticValue; - static float lightQuadraticRadiusMult; - - static bool lightOutQuadInLin; - - ESMS::CellStore &cell; - MWWorld::Environment &mEnvironment; - MWScene &scene; - MWWorld::PhysicsSystem *mPhysics; - - /// The scene node that contains all objects belonging to this - /// cell. - Ogre::SceneNode *base; - - Ogre::SceneNode *insert; - std::string mInsertMesh; - Ogre::SceneNode *npcPart; - - // 0 normal, 1 more bright, 2 max - int ambientMode; - - Ogre::ColourValue ambientColor; - - /// start inserting a new reference. - virtual void insertBegin (ESM::CellRef &ref, MWWorld::RefData& refData, bool static_ = false); - virtual void rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements); - virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements); - /// insert a mesh related to the most recent insertBegin call. - virtual void insertMesh(const std::string &mesh); - virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements); - virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst); - - virtual void insertObjectPhysics(); - - virtual void insertActorPhysics(); - - /// insert a light related to the most recent insertBegin call. - virtual void insertLight(float r, float g, float b, float radius); - - /// finish inserting a new reference and return a handle to it. - virtual std::string insertEnd (bool Enable); - - /// configure lighting according to cell - void configureAmbient(); - - /// configure fog according to cell - void configureFog(); - - void setAmbientMode(); - - - public: - - InteriorCellRender(ESMS::CellStore &_cell, MWWorld::Environment& environment, - MWScene &_scene, MWWorld::PhysicsSystem *physics) - : cell(_cell), mEnvironment (environment), scene(_scene), base(NULL), insert(NULL), ambientMode (0) - { - mPhysics = physics; - } - - virtual ~InteriorCellRender() { destroy(); } - - /// Make the cell visible. Load the cell if necessary. - //virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements); - virtual void show(); - - /// Remove the cell from rendering, but don't remove it from - /// memory. - virtual void hide(); - - /// Destroy all rendering objects connected with this cell. - virtual void destroy(); // comment by Zini: shouldn't this go into the destructor? - - /// Switch through lighting modes. - void toggleLight(); - - /// Make the reference with the given handle visible. - virtual void enable (const std::string& handle); - - /// Make the reference with the given handle invisible. - virtual void disable (const std::string& handle); - - /// Remove the reference with the given handle permanently from the scene. - virtual void deleteObject (const std::string& handle); - }; -} - -#endif diff --git a/apps/openmw/mwrender/mwscene.cpp b/apps/openmw/mwrender/mwscene.cpp deleted file mode 100644 index 900b4d249..000000000 --- a/apps/openmw/mwrender/mwscene.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "mwscene.hpp" - -#include - -#include "OgreRoot.h" -#include "OgreRenderWindow.h" -#include "OgreSceneManager.h" -#include "OgreViewport.h" -#include "OgreCamera.h" -#include "OgreTextureManager.h" - -#include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone -#include "../mwworld/ptr.hpp" -#include - -#include "player.hpp" - -using namespace MWRender; -using namespace Ogre; - -MWScene::MWScene(OEngine::Render::OgreRenderer &_rend , OEngine::Physic::PhysicEngine* physEng) - : rend(_rend) -{ - eng = physEng; - rend.createScene("PlayerCam", 55, 5); - - // Set default mipmap level (NB some APIs ignore this) - TextureManager::getSingleton().setDefaultNumMipmaps(5); - - // Load resources - ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); - - // Turn the entire scene (represented by the 'root' node) -90 - // degrees around the x axis. This makes Z go upwards, and Y go into - // the screen (when x is to the right.) This is the orientation that - // Morrowind uses, and it automagically makes everything work as it - // should. - SceneNode *rt = rend.getScene()->getRootSceneNode(); - mwRoot = rt->createChildSceneNode(); - mwRoot->pitch(Degree(-90)); - - //used to obtain ingame information of ogre objects (which are faced or selected) - mRaySceneQuery = rend.getScene()->createRayQuery(Ray()); - - Ogre::SceneNode *playerNode = mwRoot->createChildSceneNode ("player"); - playerNode->pitch(Degree(90)); - Ogre::SceneNode *cameraYawNode = playerNode->createChildSceneNode(); - Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode(); - cameraPitchNode->attachObject(getCamera()); - - - mPlayer = new MWRender::Player (getCamera(), playerNode->getName()); -} - -MWScene::~MWScene() -{ - delete mPlayer; -} - -std::pair MWScene::getFacedHandle (MWWorld::World& world) -{ - std::string handle = ""; - - //get a ray pointing to the center of the viewport - Ray centerRay = getCamera()->getCameraToViewportRay( - getViewport()->getWidth()/2, - getViewport()->getHeight()/2); - //let's avoid the capsule shape of the player. - centerRay.setOrigin(centerRay.getOrigin() + 20*centerRay.getDirection()); - btVector3 from(centerRay.getOrigin().x,-centerRay.getOrigin().z,centerRay.getOrigin().y); - btVector3 to(centerRay.getPoint(500).x,-centerRay.getPoint(500).z,centerRay.getPoint(500).y); - - return eng->rayTest(from,to); -} - -bool MWScene::toggleRenderMode (int mode) -{ - switch (mode) - { - case MWWorld::World::Render_CollisionDebug: - - // TODO use a proper function instead of accessing the member variable - // directly. - eng->setDebugRenderingMode (!eng->isDebugCreated); - return eng->isDebugCreated; - } - - return false; -} diff --git a/apps/openmw/mwrender/mwscene.hpp b/apps/openmw/mwrender/mwscene.hpp deleted file mode 100644 index 918679035..000000000 --- a/apps/openmw/mwrender/mwscene.hpp +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef _GAME_RENDER_MWSCENE_H -#define _GAME_RENDER_MWSCENE_H - -#include -#include -#include - -#include -#include - -namespace Ogre -{ - class Camera; - class Viewport; - class SceneManager; - class SceneNode; - class RaySceneQuery; - class Quaternion; - class Vector3; -} - -namespace MWWorld -{ - class World; -} - -namespace MWRender -{ - class Player; - - /// \brief 3D-scene (rendering and physics) - - class MWScene - { - OEngine::Render::OgreRenderer &rend; - - /// Root node for all objects added to the scene. This is rotated so - /// that the OGRE coordinate system matches that used internally in - /// Morrowind. - Ogre::SceneNode *mwRoot; - Ogre::RaySceneQuery *mRaySceneQuery; - - OEngine::Physic::PhysicEngine* eng; - - MWRender::Player *mPlayer; - - public: - - MWScene (OEngine::Render::OgreRenderer &_rend , OEngine::Physic::PhysicEngine* physEng); - - ~MWScene(); - - Ogre::Camera *getCamera() { return rend.getCamera(); } - Ogre::SceneNode *getRoot() { return mwRoot; } - Ogre::SceneManager *getMgr() { return rend.getScene(); } - Ogre::Viewport *getViewport() { return rend.getViewport(); } - Ogre::RaySceneQuery *getRaySceneQuery() { return mRaySceneQuery; } - MWRender::Player *getPlayer() { return mPlayer; } - - /// Gets the handle of the object the player is looking at - /// pair - /// name is empty and distance = -1 if there is no object which - /// can be faced - std::pair getFacedHandle (MWWorld::World& world); - - /// Toggle render mode - /// \todo Using an int instead of a enum here to avoid cyclic includes. Will be fixed - /// when the mw*-refactoring is done. - /// \return Resulting mode - bool toggleRenderMode (int mode); - }; -} - -#endif diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp new file mode 100644 index 000000000..ef5c10559 --- /dev/null +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -0,0 +1,308 @@ +#include "npcanimation.hpp" +#include "../mwworld/world.hpp" + + +using namespace Ogre; +using namespace NifOgre; +namespace MWRender{ +NpcAnimation::~NpcAnimation(){ + +} + + +NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,OEngine::Render::OgreRenderer& _rend): Animation(_env,_rend){ + ESMS::LiveCellRef *ref = + ptr.get(); + + //Part selection on last character of the file string + // " Tri Chest + // * Tri Tail + // : Tri Left Foot + // < Tri Right Foot + // > Tri Left Hand + // ? Tri Right Hand + // | Normal + + //Mirroring Parts on second to last character + //suffix == '*' + // vector = Ogre::Vector3(-1,1,1); + // suffix == '?' + // vector = Ogre::Vector3(1,-1,1); + // suffix == '<' + // vector = Ogre::Vector3(1,1,-1); + + + std::string hairID = ref->base->hair; + std::string headID = ref->base->head; + std::string npcName = ref->base->name; + //ESMStore::Races r = + const ESM::Race* race = mEnvironment.mWorld->getStore().races.find(ref->base->race); + + + std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); + char secondtolast = bodyRaceID.at(bodyRaceID.length() - 2); + bool female = tolower(secondtolast) == 'f'; + bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; + /*std::cout << "Race: " << ref->base->race ; + if(female){ + std::cout << " Sex: Female" << " Height: " << race->data.height.female << "\n"; + } + else{ + std::cout << " Sex: Male" << " Height: " << race->data.height.male << "\n"; + }*/ + + + + std::string smodel = "meshes\\base_anim.nif"; + if(beast) + smodel = "meshes\\base_animkna.nif"; + + insert = ptr.getRefData().getBaseNode(); + assert(insert); + + NifOgre::NIFLoader::load(smodel); + + base = mRend.getScene()->createEntity(smodel); + base->setSkipAnimationStateUpdate(true); //Magical line of code, this makes the bones + //stay in the same place when we skipanim, or open a gui window + + + if((transformations = (NIFLoader::getSingletonPtr())->getAnim(smodel))){ + + for(unsigned int init = 0; init < transformations->size(); init++){ + rindexI.push_back(0); + tindexI.push_back(0); + } + + stopTime = transformations->begin()->getStopTime(); + startTime = transformations->begin()->getStartTime(); + } + textmappings = NIFLoader::getSingletonPtr()->getTextIndices(smodel); + insert->attachObject(base); + + if(female) + insert->scale(race->data.height.female, race->data.height.female, race->data.height.female); + else + insert->scale(race->data.height.male, race->data.height.male, race->data.height.male); + std::string headModel = "meshes\\" + + mEnvironment.mWorld->getStore().bodyParts.find(headID)->model; + + std::string hairModel = "meshes\\" + + mEnvironment.mWorld->getStore().bodyParts.find(hairID)->model; + const ESM::BodyPart *chest = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "chest"); + const ESM::BodyPart *upperleg = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg"); + const ESM::BodyPart *groin = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin"); + const ESM::BodyPart *arml = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper arm"); //We need two + const ESM::BodyPart *neck = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "neck"); + const ESM::BodyPart *knee = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "knee"); + const ESM::BodyPart *ankle = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "ankle"); + const ESM::BodyPart *foot = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "foot"); + const ESM::BodyPart *feet = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "feet"); + const ESM::BodyPart *tail = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "tail"); + const ESM::BodyPart *wristl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "wrist"); //We need two + const ESM::BodyPart *forearml = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "forearm"); //We need two + const ESM::BodyPart *handl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "hand"); //We need two + const ESM::BodyPart *hair = mEnvironment.mWorld->getStore().bodyParts.search(hairID); + const ESM::BodyPart *head = mEnvironment.mWorld->getStore().bodyParts.search(headID); + if(bodyRaceID == "b_n_argonian_f_") + forearml = mEnvironment.mWorld->getStore().bodyParts.search ("b_n_argonian_m_forearm"); //We need two + if(!handl) + handl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands"); + //const ESM::BodyPart* claviclel = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "clavicle"); + //const ESM::BodyPart* clavicler = claviclel; + const ESM::BodyPart* handr = handl; + const ESM::BodyPart* forearmr = forearml; + const ESM::BodyPart* wristr = wristl; + const ESM::BodyPart* armr = arml; + + + if(upperleg){ + insertBoundedPart("meshes\\" + upperleg->model + "*|", "Left Upper Leg"); + insertBoundedPart("meshes\\" + upperleg->model, "Right Upper Leg"); + + } + if(foot){ + if(bodyRaceID.compare("b_n_khajiit_m_") == 0) + { + feet = foot; + } + else + { + insertBoundedPart("meshes\\" + foot->model, "Right Foot"); + insertBoundedPart("meshes\\" + foot->model + "*|", "Left Foot"); + } + } + if(groin){ + insertBoundedPart("meshes\\" + groin->model, "Groin"); + } + if(knee) + { + insertBoundedPart("meshes\\" + knee->model + "*|", "Left Knee"); //e + insertBoundedPart("meshes\\" + knee->model, "Right Knee"); //e + + } + if(ankle){ + + insertBoundedPart("meshes\\" + ankle->model + "*|", "Left Ankle"); //Ogre::Quaternion(Ogre::Radian(3.14 / 4), Ogre::Vector3(1, 0, 0)),blank); //1,0,0, blank); + insertBoundedPart("meshes\\" + ankle->model, "Right Ankle"); + } + if (armr){ + insertBoundedPart("meshes\\" + armr->model, "Right Upper Arm"); + } + if(arml){ + insertBoundedPart("meshes\\" + arml->model + "*|", "Left Upper Arm"); + } + + if (forearmr) + { + insertBoundedPart("meshes\\" + forearmr->model, "Right Forearm"); + } + if(forearml) + insertBoundedPart("meshes\\" + forearml->model + "*|", "Left Forearm"); + + if (wristr) + { + insertBoundedPart("meshes\\" + wristr->model, "Right Wrist"); + } + + if(wristl) + insertBoundedPart("meshes\\" + wristl->model + "*|", "Left Wrist"); + + + + + + /*if(claviclel) + insertBoundedPart("meshes\\" + claviclel->model + "*|", "Left Clavicle", base); + if(clavicler) + insertBoundedPart("meshes\\" + clavicler->model , "Right Clavicle", base);*/ + + + if(neck) + { + insertBoundedPart("meshes\\" + neck->model, "Neck"); + } + if(head) + insertBoundedPart("meshes\\" + head->model, "Head"); + if(hair) + insertBoundedPart("meshes\\" + hair->model, "Head"); + + if (chest){ + insertFreePart("meshes\\" + chest->model, ">\"", insert); + + + } + if (handr){ + insertFreePart("meshes\\" + handr->model , ">?", insert); + + } + if (handl){ + insertFreePart("meshes\\" + handl->model, ">>", insert); + + } + if(tail){ + insertFreePart("meshes\\" + tail->model, ">*", insert); + } + if(feet){ + std::string num = getUniqueID(feet->model); + insertFreePart("meshes\\" + feet->model,"><", insert); + insertFreePart("meshes\\" + feet->model,">:", insert); + } + //originalpos = insert->_getWorldAABB().getCenter(); + //originalscenenode = insert->getPosition(); +} + +Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, std::string bonename){ + NIFLoader::load(mesh); + Entity* ent = mRend.getScene()->createEntity(mesh); + + base->attachObjectToBone(bonename, ent); + return ent; +} +void NpcAnimation::insertFreePart(const std::string &mesh, const std::string suffix, Ogre::SceneNode* insert){ + std::string meshNumbered = mesh + getUniqueID(mesh + suffix) + suffix; + NIFLoader::load(meshNumbered); + + Ogre::Entity* ent = mRend.getScene()->createEntity(meshNumbered); + + /*MaterialPtr material = ent->getSubEntity(0)->getMaterial(); + material->removeAllTechniques(); + + Ogre::Technique* tech = material->createTechnique(); + + Pass* pass2 = tech->createPass(); + pass2->setVertexProgram("Ogre/HardwareSkinningTwoWeights"); + pass2->setColourWriteEnabled(false); + //tech->setSchemeName("blahblah");*/ + + + insert->attachObject(ent); + entityparts.push_back(ent); + shapes = ((NIFLoader::getSingletonPtr())->getShapes(mesh + "0000" + suffix)); + if(shapes){ + shapeparts.push_back(shapes); + handleShapes(shapes, ent, base->getSkeleton()); + } + + +} + + +void NpcAnimation::runAnimation(float timepassed){ + //1. Add the amount of time passed to time + + //2. Handle the animation transforms dependent on time + + //3. Handle the shapes dependent on animation transforms + if(animate > 0){ + time += timepassed; + + if(time > stopTime){ + animate--; + + if(animate == 0) + time = stopTime; + else + time = startTime + (time - stopTime); + } + + handleAnimationTransforms(); + Ogre::Vector3 current = insert->_getWorldAABB().getCenter(); + + //This is the attempt at npc physics + //mEnvironment.mWorld->setObjectPhysicsPosition(insert->getName(), current); + + + + /*if(base->hasSkeleton()) + { + + Ogre::Quaternion boneQuat = rotate; + Ogre::Vector3 boneTrans = trans; + mEnvironment.mWorld->setObjectPhysicsPosition(insert->getName(), boneTrans + insert->getPosition()); + //mEnvironment.mWorld->setObjectPhysicsRotation(insert->getName(), boneQuat * insert->getOrientation()); + + }*/ + + + std::vector*>::iterator shapepartsiter = shapeparts.begin(); + std::vector::iterator entitypartsiter = entityparts.begin(); + while(shapepartsiter != shapeparts.end()) + { + std::vector* shapes = *shapepartsiter; + Ogre::Entity* theentity = *entitypartsiter; + /* + Pass* pass = theentity->getSubEntity(0)->getMaterial()->getBestTechnique()->getPass(0); + if (pass->hasVertexProgram() && pass->getVertexProgram()->isSkeletalAnimationIncluded()) + std::cout << "It's hardware\n"; + else + std::cout << "It's software\n";*/ + + handleShapes(shapes, theentity, theentity->getSkeleton()); + shapepartsiter++; + entitypartsiter++; + } + } + +} +} diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp new file mode 100644 index 000000000..e8ce735f7 --- /dev/null +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -0,0 +1,30 @@ +#ifndef _GAME_RENDER_NPCANIMATION_H +#define _GAME_RENDER_NPCANIMATION_H +#include "animation.hpp" +#include +#include +#include +#include +#include + +#include "../mwworld/refdata.hpp" +#include "../mwworld/ptr.hpp" +#include "../mwworld/environment.hpp" +#include "components/nifogre/ogre_nif_loader.hpp" + +namespace MWRender{ + +class NpcAnimation: public Animation{ + + + + public: + NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend); + ~NpcAnimation(); + Ogre::Entity* insertBoundedPart(const std::string &mesh, std::string bonename); + void insertFreePart(const std::string &mesh, const std::string suffix, Ogre::SceneNode* insert); + virtual void runAnimation(float timepassed); + +}; +} +#endif \ No newline at end of file diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp new file mode 100644 index 000000000..1e3b4dda0 --- /dev/null +++ b/apps/openmw/mwrender/objects.cpp @@ -0,0 +1,185 @@ +#include "objects.hpp" +#include +#include + +using namespace Ogre; +using namespace MWRender; + + +bool Objects::lightConst = false; +float Objects::lightConstValue = 0.0f; + +bool Objects::lightLinear = true; +int Objects::lightLinearMethod = 1; +float Objects::lightLinearValue = 3; +float Objects::lightLinearRadiusMult = 1; + +bool Objects::lightQuadratic = false; +int Objects::lightQuadraticMethod = 2; +float Objects::lightQuadraticValue = 16; +float Objects::lightQuadraticRadiusMult = 1; + +bool Objects::lightOutQuadInLin = false; + +int Objects::uniqueID = 0; + +void Objects::setMwRoot(Ogre::SceneNode* root){ + mMwRoot = root; +} +void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){ + Ogre::SceneNode* root = mMwRoot; + Ogre::SceneNode* cellnode; + if(mCellSceneNodes.find(ptr.getCell()) == mCellSceneNodes.end()) + { + //Create the scenenode and put it in the map + cellnode = root->createChildSceneNode(); + mCellSceneNodes[ptr.getCell()] = cellnode; + } + else + { + cellnode = mCellSceneNodes[ptr.getCell()]; + } + + Ogre::SceneNode* insert = cellnode->createChildSceneNode(); + const float *f = ptr.getRefData().getPosition().pos; + insert->setPosition(f[0], f[1], f[2]); + insert->setScale(ptr.getCellRef().scale, ptr.getCellRef().scale, ptr.getCellRef().scale); + + // Convert MW rotation to a quaternion: + f = ptr.getCellRef().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); + if (!enabled) + insert->setVisible (false); + ptr.getRefData().setBaseNode(insert); + isStatic = static_; + + +} +void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh){ + Ogre::SceneNode* insert = ptr.getRefData().getBaseNode(); + assert(insert); + + NifOgre::NIFLoader::load(mesh); + Entity *ent = mRend.getScene()->createEntity(mesh); + + if(!isStatic) + { + insert->attachObject(ent); + } + else + { + Ogre::StaticGeometry* sg = 0; + if(mSG.find(ptr.getCell()) == mSG.end()) + { + uniqueID = uniqueID +1; + sg = mRend.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); + //Create the scenenode and put it in the map + mSG[ptr.getCell()] = sg; + } + else + { + sg = mSG[ptr.getCell()]; + } + + sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale()); + sg->setRegionDimensions(Ogre::Vector3(100000,10000,100000)); + + + mRend.getScene()->destroyEntity(ent); + } + + +} +void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius){ + Ogre::SceneNode* insert = mRend.getScene()->getSceneNode(ptr.getRefData().getHandle()); + assert(insert); + Ogre::Light *light = mRend.getScene()->createLight(); + light->setDiffuseColour (r, g, b); + + float cval=0.0f, lval=0.0f, qval=0.0f; + + if(lightConst) + cval = lightConstValue; + if(!lightOutQuadInLin) + { + if(lightLinear) + radius *= lightLinearRadiusMult; + if(lightQuadratic) + radius *= lightQuadraticRadiusMult; + + if(lightLinear) + lval = lightLinearValue / pow(radius, lightLinearMethod); + if(lightQuadratic) + qval = lightQuadraticValue / pow(radius, lightQuadraticMethod); + } + else + { + // FIXME: + // Do quadratic or linear, depending if we're in an exterior or interior + // cell, respectively. Ignore lightLinear and lightQuadratic. + } + + light->setAttenuation(10*radius, cval, lval, qval); + + insert->attachObject(light); +} + +bool Objects::deleteObject (const MWWorld::Ptr& ptr) +{ + if (Ogre::SceneNode *base = ptr.getRefData().getBaseNode()) + { + Ogre::SceneNode *parent = base->getParentSceneNode(); + + for (std::map::const_iterator iter ( + mCellSceneNodes.begin()); iter!=mCellSceneNodes.end(); ++iter) + if (iter->second==parent) + { + base->removeAndDestroyAllChildren(); + mRend.getScene()->destroySceneNode (base); + ptr.getRefData().setBaseNode (0); + return true; + } + + return false; + } + + return true; +} + +void Objects::removeCell(MWWorld::Ptr::CellStore* store){ + if(mCellSceneNodes.find(store) != mCellSceneNodes.end()) + { + Ogre::SceneNode* base = mCellSceneNodes[store]; + base->removeAndDestroyAllChildren(); + mCellSceneNodes.erase(store); + mRend.getScene()->destroySceneNode(base); + base = 0; + } + + + if(mSG.find(store) != mSG.end()) + { + Ogre::StaticGeometry* sg = mSG[store]; + mSG.erase(store); + mRend.getScene()->destroyStaticGeometry (sg); + sg = 0; + } +} +void Objects::buildStaticGeometry(ESMS::CellStore& cell){ + if(mSG.find(&cell) != mSG.end()) + { + Ogre::StaticGeometry* sg = mSG[&cell]; + sg->build(); + } +} diff --git a/apps/openmw/mwrender/objects.hpp b/apps/openmw/mwrender/objects.hpp new file mode 100644 index 000000000..6cd465fdd --- /dev/null +++ b/apps/openmw/mwrender/objects.hpp @@ -0,0 +1,48 @@ +#ifndef _GAME_RENDER_OBJECTS_H +#define _GAME_RENDER_OBJECTS_H + +#include "components/esm_store/cell_store.hpp" + +#include "../mwworld/refdata.hpp" +#include "../mwworld/ptr.hpp" +#include + +namespace MWRender{ + +class Objects{ + OEngine::Render::OgreRenderer &mRend; + std::map mCellSceneNodes; + std::map mSG; + Ogre::SceneNode* mMwRoot; + bool isStatic; + static int uniqueID; + static bool lightConst; + static float lightConstValue; + + static bool lightLinear; + static int lightLinearMethod; + static float lightLinearValue; + static float lightLinearRadiusMult; + + static bool lightQuadratic; + static int lightQuadraticMethod; + static float lightQuadraticValue; + static float lightQuadraticRadiusMult; + + static bool lightOutQuadInLin; +public: + Objects(OEngine::Render::OgreRenderer& _rend): mRend(_rend){} + ~Objects(){} + void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_); + void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh); + void insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius); + + bool deleteObject (const MWWorld::Ptr& ptr); + ///< \return found? + + void removeCell(MWWorld::Ptr::CellStore* store); + void buildStaticGeometry(ESMS::CellStore &cell); + void setMwRoot(Ogre::SceneNode* root); +}; +} +#endif diff --git a/apps/openmw/mwrender/player.cpp b/apps/openmw/mwrender/player.cpp index 7dcaeee09..7ed921218 100644 --- a/apps/openmw/mwrender/player.cpp +++ b/apps/openmw/mwrender/player.cpp @@ -3,7 +3,7 @@ namespace MWRender { - Player::Player (Ogre::Camera *camera, const std::string& handle) - : mCamera (camera), mHandle (handle) + Player::Player (Ogre::Camera *camera, Ogre::SceneNode* node) + : mCamera (camera), mNode (node) {} } diff --git a/apps/openmw/mwrender/player.hpp b/apps/openmw/mwrender/player.hpp index f2d819116..4306b8a95 100644 --- a/apps/openmw/mwrender/player.hpp +++ b/apps/openmw/mwrender/player.hpp @@ -2,6 +2,7 @@ #define GAME_MWRENDER_PLAYER_H #include +#include namespace Ogre { @@ -14,15 +15,16 @@ namespace MWRender class Player { Ogre::Camera *mCamera; - std::string mHandle; + Ogre::SceneNode* mNode; public: - Player (Ogre::Camera *camera, const std::string& handle); + Player (Ogre::Camera *camera, Ogre::SceneNode* mNode); Ogre::Camera *getCamera() { return mCamera; } - std::string getHandle() const { return mHandle; } + std::string getHandle() const { return mNode->getName(); } + Ogre::SceneNode* getNode() {return mNode;} }; } diff --git a/apps/openmw/mwrender/rendering_manager.cpp b/apps/openmw/mwrender/rendering_manager.cpp deleted file mode 100644 index e7ef93858..000000000 --- a/apps/openmw/mwrender/rendering_manager.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "rendering_manager.hpp" - -namespace MWRender { - -RenderingManager::RenderingManager (SkyManager *skyManager) : - mSkyManager(skyManager) -{ - -} - -RenderingManager::~RenderingManager () -{ - delete mSkyManager; -} - -void RenderingManager::skyEnable () -{ - mSkyManager->enable(); -} - -void RenderingManager::skyDisable () -{ - mSkyManager->disable(); -} - -void RenderingManager::skySetHour (double hour) -{ - mSkyManager->setHour(hour); -} - - -void RenderingManager::skySetDate (int day, int month) -{ - mSkyManager->setDate(day, month); -} - -int RenderingManager::skyGetMasserPhase() const -{ - return mSkyManager->getMasserPhase(); -} - -int RenderingManager::skyGetSecundaPhase() const -{ - return mSkyManager->getSecundaPhase(); -} - -void RenderingManager::skySetMoonColour (bool red) -{ - mSkyManager->setMoonColour(red); -} - -} diff --git a/apps/openmw/mwrender/rendering_manager.hpp b/apps/openmw/mwrender/rendering_manager.hpp deleted file mode 100644 index d456716d3..000000000 --- a/apps/openmw/mwrender/rendering_manager.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _GAME_RENDERING_MANAGER_H -#define _GAME_RENDERING_MANAGER_H - - -#include "sky.hpp" - -#include "../mwworld/ptr.hpp" -#include -#include - -namespace MWRender -{ - -class RenderingManager { - public: - RenderingManager(SkyManager *skyManager); - ~RenderingManager(); - - void removeCell (MWWorld::Ptr::CellStore *store); // TODO do we want this? - - void addObject (const MWWorld::Ptr& ptr, MWWorld::Ptr::CellStore *store); - void removeObject (const MWWorld::Ptr& ptr, MWWorld::Ptr::CellStore *store); - - void moveObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& position); - void scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& scale); - void rotateObject (const MWWorld::Ptr& ptr, const::Ogre::Quaternion& orientation); - void moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Vector3& position, MWWorld::Ptr::CellStore *store); - - void setPhysicsDebugRendering (bool); - bool getPhysicsDebugRendering() const; - - void update (float duration); - - void skyEnable (); - void skyDisable (); - void skySetHour (double hour); - void skySetDate (int day, int month); - int skyGetMasserPhase() const; - int skyGetSecundaPhase() const; - void skySetMoonColour (bool red); - - private: - - SkyManager* mSkyManager; - - -}; - -} - -#endif diff --git a/apps/openmw/mwrender/renderinginterface.hpp b/apps/openmw/mwrender/renderinginterface.hpp new file mode 100644 index 000000000..03935bef6 --- /dev/null +++ b/apps/openmw/mwrender/renderinginterface.hpp @@ -0,0 +1,16 @@ +#ifndef _GAME_RENDERING_INTERFACE_H +#define _GAME_RENDERING_INTERFACE_H +namespace MWRender{ + class Objects; + class Actors; + class Player; + +class RenderingInterface{ + public: + virtual MWRender::Objects& getObjects() = 0; + virtual MWRender::Player& getPlayer() = 0; + virtual MWRender::Actors& getActors() = 0; + virtual ~RenderingInterface(){}; + }; +} +#endif \ No newline at end of file diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp new file mode 100644 index 000000000..6215c1913 --- /dev/null +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -0,0 +1,248 @@ +#include "renderingmanager.hpp" + +#include + +#include "OgreRoot.h" +#include "OgreRenderWindow.h" +#include "OgreSceneManager.h" +#include "OgreViewport.h" +#include "OgreCamera.h" +#include "OgreTextureManager.h" + +#include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone +#include "../mwworld/ptr.hpp" +#include + + +using namespace MWRender; +using namespace Ogre; + +namespace MWRender { + + + +RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment) +:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mDebugging(engine) +{ + mRendering.createScene("PlayerCam", 55, 5); + mSkyManager = MWRender::SkyManager::create(mRendering.getWindow(), mRendering.getCamera(), resDir); + + // Set default mipmap level (NB some APIs ignore this) + TextureManager::getSingleton().setDefaultNumMipmaps(5); + + // Load resources + ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); + + // Turn the entire scene (represented by the 'root' node) -90 + // degrees around the x axis. This makes Z go upwards, and Y go into + // the screen (when x is to the right.) This is the orientation that + // Morrowind uses, and it automagically makes everything work as it + // should. + SceneNode *rt = mRendering.getScene()->getRootSceneNode(); + mMwRoot = rt->createChildSceneNode(); + mMwRoot->pitch(Degree(-90)); + mObjects.setMwRoot(mMwRoot); + mActors.setMwRoot(mMwRoot); + + //used to obtain ingame information of ogre objects (which are faced or selected) + mRaySceneQuery = mRendering.getScene()->createRayQuery(Ray()); + + Ogre::SceneNode *playerNode = mMwRoot->createChildSceneNode ("player"); + playerNode->pitch(Degree(90)); + Ogre::SceneNode *cameraYawNode = playerNode->createChildSceneNode(); + Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode(); + cameraPitchNode->attachObject(mRendering.getCamera()); + + mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode); +} + +RenderingManager::~RenderingManager () +{ + delete mPlayer; + delete mSkyManager; +} + + +MWRender::Objects& RenderingManager::getObjects(){ + return mObjects; +} +MWRender::Actors& RenderingManager::getActors(){ + return mActors; +} + +MWRender::Player& RenderingManager::getPlayer(){ + return (*mPlayer); +} + +void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store){ + mObjects.removeCell(store); + mActors.removeCell(store); +} + +void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store) +{ + mObjects.buildStaticGeometry (*store); +} + +void RenderingManager::addObject (const MWWorld::Ptr& ptr){ + const MWWorld::Class& class_ = + MWWorld::Class::get (ptr); + class_.insertObjectRendering(ptr, *this); + +} +void RenderingManager::removeObject (const MWWorld::Ptr& ptr) +{ + if (!mObjects.deleteObject (ptr)) + { + /// \todo delete non-object MW-references + } + if (!mActors.deleteObject (ptr)) + { + /// \todo delete non-object MW-references + } +} + +void RenderingManager::moveObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& position) +{ + /// \todo move this to the rendering-subsystems + mRendering.getScene()->getSceneNode (ptr.getRefData().getHandle())-> + setPosition (position); +} + +void RenderingManager::scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& scale){ + +} +void RenderingManager::rotateObject (const MWWorld::Ptr& ptr, const::Ogre::Quaternion& orientation){ + +} +void RenderingManager::moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Vector3& position, MWWorld::Ptr::CellStore *store){ + +} + +void RenderingManager::update (float duration){ + + +} + +void RenderingManager::skyEnable () +{ + mSkyManager->enable(); +} + +void RenderingManager::skyDisable () +{ + mSkyManager->disable(); +} + +void RenderingManager::skySetHour (double hour) +{ + mSkyManager->setHour(hour); +} + + +void RenderingManager::skySetDate (int day, int month) +{ + mSkyManager->setDate(day, month); +} + +int RenderingManager::skyGetMasserPhase() const +{ + return mSkyManager->getMasserPhase(); +} + +int RenderingManager::skyGetSecundaPhase() const +{ + return mSkyManager->getSecundaPhase(); +} + +void RenderingManager::skySetMoonColour (bool red) +{ + mSkyManager->setMoonColour(red); +} +bool RenderingManager::toggleRenderMode(int mode){ + return mDebugging.toggleRenderMode(mode); +} + +void RenderingManager::configureFog(ESMS::CellStore &mCell) +{ + Ogre::ColourValue color; + color.setAsABGR (mCell.cell->ambi.fog); + + float high = 4500 + 9000 * (1-mCell.cell->ambi.fogDensity); + float low = 200; + + mRendering.getScene()->setFog (FOG_LINEAR, color, 0, low, high); + mRendering.getCamera()->setFarClipDistance (high + 10); + mRendering.getViewport()->setBackgroundColour (color); +} + +void RenderingManager::setAmbientMode() +{ + switch (mAmbientMode) + { + case 0: + + mRendering.getScene()->setAmbientLight(mAmbientColor); + break; + + case 1: + + mRendering.getScene()->setAmbientLight(0.7f*mAmbientColor + 0.3f*ColourValue(1,1,1)); + break; + + case 2: + + mRendering.getScene()->setAmbientLight(ColourValue(1,1,1)); + break; + } +} + +void RenderingManager::configureAmbient(ESMS::CellStore &mCell) +{ + mAmbientColor.setAsABGR (mCell.cell->ambi.ambient); + setAmbientMode(); + + // Create a "sun" that shines light downwards. It doesn't look + // completely right, but leave it for now. + Ogre::Light *light = mRendering.getScene()->createLight(); + Ogre::ColourValue colour; + colour.setAsABGR (mCell.cell->ambi.sunlight); + light->setDiffuseColour (colour); + light->setType(Ogre::Light::LT_DIRECTIONAL); + light->setDirection(0,-1,0); +} +// Switch through lighting modes. + +void RenderingManager::toggleLight() +{ + if (mAmbientMode==2) + mAmbientMode = 0; + else + ++mAmbientMode; + + switch (mAmbientMode) + { + case 0: std::cout << "Setting lights to normal\n"; break; + case 1: std::cout << "Turning the lights up\n"; break; + case 2: std::cout << "Turning the lights to full\n"; break; + } + + setAmbientMode(); +} + +void RenderingManager::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, + int mode, int number) +{ + mActors.playAnimationGroup(ptr, groupName, mode, number); +} + +void RenderingManager::skipAnimation (const MWWorld::Ptr& ptr) +{ + mActors.skipAnimation(ptr); +} +void RenderingManager::addTime(){ + mActors.addTime(); + //Notify each animation that time has passed +} + +} diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp new file mode 100644 index 000000000..747a3e0ee --- /dev/null +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -0,0 +1,138 @@ +#ifndef _GAME_RENDERING_MANAGER_H +#define _GAME_RENDERING_MANAGER_H + + +#include "sky.hpp" +#include "debugging.hpp" + +#include "../mwworld/class.hpp" + +#include +#include +#include + +#include +#include + +#include "../mwworld/ptr.hpp" + +#include + +#include "renderinginterface.hpp" + +#include "objects.hpp" +#include "actors.hpp" +#include "player.hpp" + +namespace Ogre +{ + class Camera; + class Viewport; + class SceneManager; + class SceneNode; + class RaySceneQuery; + class Quaternion; + class Vector3; +} + +namespace MWWorld +{ + class World; +} + +namespace MWRender +{ + + + +class RenderingManager: private RenderingInterface { + + private: + + + virtual MWRender::Objects& getObjects(); + virtual MWRender::Actors& getActors(); + + public: + RenderingManager(OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment); + virtual ~RenderingManager(); + + virtual MWRender::Player& getPlayer(); /// \todo move this to private again as soon as + /// MWWorld::Player has been rewritten to not need access + /// to internal details of the rendering system anymore + + void toggleLight(); + bool toggleRenderMode(int mode); + + void removeCell (MWWorld::Ptr::CellStore *store); + + /// \todo this function should be removed later. Instead the rendering subsystems should track + /// when rebatching is needed and update automatically at the end of each frame. + void cellAdded (MWWorld::Ptr::CellStore *store); + + void addObject (const MWWorld::Ptr& ptr); + void removeObject (const MWWorld::Ptr& ptr); + + void moveObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& position); + void scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& scale); + void rotateObject (const MWWorld::Ptr& ptr, const::Ogre::Quaternion& orientation); + + /// \param store Cell the object was in previously (\a ptr has already been updated to the new cell). + void moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Vector3& position, MWWorld::Ptr::CellStore *store); + + void update (float duration); + + void skyEnable (); + void skyDisable (); + void skySetHour (double hour); + void skySetDate (int day, int month); + int skyGetMasserPhase() const; + int skyGetSecundaPhase() const; + void skySetMoonColour (bool red); + void configureAmbient(ESMS::CellStore &mCell); + /// configure fog according to cell + void configureFog(ESMS::CellStore &mCell); + + void playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, + int number = 1); + ///< Run animation for a MW-reference. Calls to this function for references that are currently not + /// in the rendered scene should be ignored. + /// + /// \param mode: 0 normal, 1 immediate start, 2 immediate loop + /// \param number How offen the animation should be run + + void skipAnimation (const MWWorld::Ptr& ptr); + ///< Skip the animation for the given MW-reference for one frame. Calls to this function for + /// references that are currently not in the rendered scene should be ignored. + + void addTime(); + + private: + + void setAmbientMode(); + SkyManager* mSkyManager; + OEngine::Render::OgreRenderer &mRendering; + + MWRender::Objects mObjects; + MWRender::Actors mActors; + + // 0 normal, 1 more bright, 2 max + int mAmbientMode; + + Ogre::ColourValue mAmbientColor; + + /// Root node for all objects added to the scene. This is rotated so + /// that the OGRE coordinate system matches that used internally in + /// Morrowind. + Ogre::SceneNode *mMwRoot; + Ogre::RaySceneQuery *mRaySceneQuery; + + OEngine::Physic::PhysicEngine* mPhysicsEngine; + + MWRender::Player *mPlayer; + MWRender::Debugging mDebugging; +}; + +} + +#endif diff --git a/apps/openmw/mwscript/animationextensions.cpp b/apps/openmw/mwscript/animationextensions.cpp new file mode 100644 index 000000000..184be83db --- /dev/null +++ b/apps/openmw/mwscript/animationextensions.cpp @@ -0,0 +1,127 @@ + +#include "animationextensions.hpp" + +#include + +#include + +#include +#include +#include + +#include "../mwworld/world.hpp" + +#include "interpretercontext.hpp" +#include "ref.hpp" + +namespace MWScript +{ + namespace Animation + { + template + class OpSkipAnim : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + InterpreterContext& context = + static_cast (runtime.getContext()); + + context.getWorld().skipAnimation (ptr); + } + }; + + template + class OpPlayAnim : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + MWWorld::Ptr ptr = R()(runtime); + + InterpreterContext& context = + static_cast (runtime.getContext()); + + std::string group = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer mode = 0; + + if (arg0==1) + { + mode = runtime[0].mInteger; + runtime.pop(); + + if (mode<0 || mode>2) + throw std::runtime_error ("animation mode out of range"); + } + + context.getWorld().playAnimationGroup (ptr, group, mode, 1); + } + }; + + template + class OpLoopAnim : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + MWWorld::Ptr ptr = R()(runtime); + + InterpreterContext& context = + static_cast (runtime.getContext()); + + std::string group = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer loops = runtime[0].mInteger; + runtime.pop(); + + if (loops<0) + throw std::runtime_error ("number of animation loops must be non-negative"); + + Interpreter::Type_Integer mode = 0; + + if (arg0==1) + { + mode = runtime[0].mInteger; + runtime.pop(); + + if (mode<0 || mode>2) + throw std::runtime_error ("animation mode out of range"); + } + + context.getWorld().playAnimationGroup (ptr, group, mode, loops); + } + }; + + const int opcodeSkipAnim = 0x2000138; + const int opcodeSkipAnimExplicit = 0x2000139; + const int opcodePlayAnim = 0x20006; + const int opcodePlayAnimExplicit = 0x20007; + const int opcodeLoopAnim = 0x20008; + const int opcodeLoopAnimExplicit = 0x20009; + + void registerExtensions (Compiler::Extensions& extensions) + { + extensions.registerInstruction ("skipanim", "", opcodeSkipAnim, opcodeSkipAnimExplicit); + extensions.registerInstruction ("playgroup", "c/l", opcodePlayAnim, opcodePlayAnimExplicit); + extensions.registerInstruction ("loopgroup", "cl/l", opcodeLoopAnim, opcodeLoopAnimExplicit); + } + + void installOpcodes (Interpreter::Interpreter& interpreter) + { + interpreter.installSegment5 (opcodeSkipAnim, new OpSkipAnim); + interpreter.installSegment5 (opcodeSkipAnimExplicit, new OpSkipAnim); + interpreter.installSegment3 (opcodePlayAnim, new OpPlayAnim); + interpreter.installSegment3 (opcodePlayAnimExplicit, new OpPlayAnim); + interpreter.installSegment3 (opcodeLoopAnim, new OpLoopAnim); + interpreter.installSegment3 (opcodeLoopAnimExplicit, new OpLoopAnim); + } + } +} diff --git a/apps/openmw/mwscript/animationextensions.hpp b/apps/openmw/mwscript/animationextensions.hpp new file mode 100644 index 000000000..ff619ab73 --- /dev/null +++ b/apps/openmw/mwscript/animationextensions.hpp @@ -0,0 +1,24 @@ +#ifndef GAME_SCRIPT_ANIMATIONEXTENSIONS_H +#define GAME_SCRIPT_ANIMATIONEXTENSIONS_H + +namespace Compiler +{ + class Extensions; +} + +namespace Interpreter +{ + class Interpreter; +} + +namespace MWScript +{ + namespace Animation + { + void registerExtensions (Compiler::Extensions& extensions); + + void installOpcodes (Interpreter::Interpreter& interpreter); + } +} + +#endif diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 33ce38cdd..183605328 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -19,7 +19,11 @@ op 0x20002: AiEscort op 0x20003: AiEscort, explicit reference op 0x20004: Lock op 0x20005: Lock, explicit reference -opcodes 0x20006-0x3ffff unused +op 0x20006: PlayAnim +op 0x20007: PlayAnim, explicit reference +op 0x20008: LoopAnim +op 0x20009: LoopAnim, explicit reference +opcodes 0x2000a-0x3ffff unused Segment 4: (not implemented yet) @@ -109,4 +113,6 @@ op 0x2000134: SetJournalIndex op 0x2000135: GetJournalIndex op 0x2000136: GetPCCell op 0x2000137: GetButtonPressed -opcodes 0x2000138-0x3ffffff unused +op 0x2000138: SkipAnim +op 0x2000139: SkipAnim, expplicit reference +opcodes 0x200013a-0x3ffffff unused diff --git a/apps/openmw/mwscript/extensions.cpp b/apps/openmw/mwscript/extensions.cpp index 86161d2b1..197494146 100644 --- a/apps/openmw/mwscript/extensions.cpp +++ b/apps/openmw/mwscript/extensions.cpp @@ -14,6 +14,7 @@ #include "aiextensions.hpp" #include "controlextensions.hpp" #include "dialogueextensions.hpp" +#include "animationextensions.hpp" namespace MWScript { @@ -29,6 +30,7 @@ namespace MWScript Ai::registerExtensions (extensions); Control::registerExtensions (extensions); Dialogue::registerExtensions (extensions); + Animation::registerExtensions (extensions); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -44,5 +46,6 @@ namespace MWScript Ai::installOpcodes (interpreter); Control::installOpcodes (interpreter); Dialogue::installOpcodes (interpreter); + Animation::installOpcodes (interpreter); } } diff --git a/apps/openmw/mwworld/cellfunctors.hpp b/apps/openmw/mwworld/cellfunctors.hpp index 5ff801f01..8bba898ce 100644 --- a/apps/openmw/mwworld/cellfunctors.hpp +++ b/apps/openmw/mwworld/cellfunctors.hpp @@ -16,12 +16,12 @@ namespace MWWorld /// List all (Ogre-)handles. struct ListHandles { - std::vector mHandles; + std::vector mHandles; bool operator() (ESM::CellRef& ref, RefData& data) { - std::string handle = data.getHandle(); - if (!handle.empty()) + Ogre::SceneNode* handle = data.getBaseNode(); + if (handle) mHandles.push_back (handle); return true; } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 670cf90b2..b4f93576a 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -21,10 +21,12 @@ namespace MWWorld throw std::runtime_error ("class does not support ID retrieval"); } - void Class::insertObj (const Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const + void Class::insertObjectRendering (const Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { + } + void Class::insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const{ + } void Class::enable (const Ptr& ptr, MWWorld::Environment& environment) const diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 8ad9ba58f..706b11aaa 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -9,6 +9,8 @@ #include "action.hpp" #include "containerstore.hpp" #include "refdata.hpp" +#include "../mwrender/renderinginterface.hpp" +#include "physicssystem.hpp" namespace Ogre { @@ -59,8 +61,10 @@ namespace MWWorld ///< Return ID of \a ptr or throw an exception, if class does not support ID retrieval /// (default implementation: throw an exception) - virtual void insertObj (const Ptr& ptr, MWRender::CellRenderImp& cellRender, - MWWorld::Environment& environment) const; + + + virtual void insertObjectRendering (const Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; + virtual void insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const; ///< Add reference into a cell for rendering (default implementation: don't render anything). virtual void enable (const Ptr& ptr, MWWorld::Environment& environment) const; diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index fa617a9c7..e74e201f5 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -1,3 +1,5 @@ +#include + #include "physicssystem.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/world.hpp" // FIXME @@ -10,6 +12,7 @@ #include "OgreTextureManager.h" +using namespace Ogre; namespace MWWorld { @@ -23,6 +26,22 @@ namespace MWWorld { } + std::pair PhysicsSystem::getFacedHandle (MWWorld::World& world) + { + std::string handle = ""; + + //get a ray pointing to the center of the viewport + Ray centerRay = mRender.getCamera()->getCameraToViewportRay( + mRender.getViewport()->getWidth()/2, + mRender.getViewport()->getHeight()/2); + //let's avoid the capsule shape of the player. + centerRay.setOrigin(centerRay.getOrigin() + 20*centerRay.getDirection()); + btVector3 from(centerRay.getOrigin().x,-centerRay.getOrigin().z,centerRay.getOrigin().y); + btVector3 to(centerRay.getPoint(500).x,-centerRay.getPoint(500).z,centerRay.getPoint(500).y); + + return mEngine->rayTest(from,to); + } + std::vector< std::pair > PhysicsSystem::doPhysics (float duration, const std::vector >& actors) @@ -126,6 +145,12 @@ namespace MWWorld void PhysicsSystem::rotateObject (const std::string& handle, const Ogre::Quaternion& rotation) { + if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle)) + { + // TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow + // start positions others than 0, 0, 0 + act->setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w)); + } } void PhysicsSystem::scaleObject (const std::string& handle, float scale) @@ -137,28 +162,43 @@ namespace MWWorld { for(std::map::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) { - OEngine::Physic::PhysicActor* act = it->second; - bool cmode = act->getCollisionMode(); - if(cmode) + if (it->first=="player") { - act->enableCollisions(false); - act->setGravity(0.); - act->setVerticalVelocity(0); - mFreeFly = true; - return false; - } - else - { - mFreeFly = false; - act->enableCollisions(true); - act->setGravity(4.); - act->setVerticalVelocity(0); - return true; + OEngine::Physic::PhysicActor* act = it->second; + + bool cmode = act->getCollisionMode(); + if(cmode) + { + act->enableCollisions(false); + act->setGravity(0.); + act->setVerticalVelocity(0); + mFreeFly = true; + return false; + } + else + { + mFreeFly = false; + act->enableCollisions(true); + act->setGravity(4.); + act->setVerticalVelocity(0); + return true; + } } } - return false; // This should never happen, but it shall not bother us now, since - // this part of the code needs a rewrite anyway. + throw std::logic_error ("can't find player"); } + void PhysicsSystem::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string model){ + Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); + addObject (node->getName(), model, node->getOrientation(), + node->getScale().x, node->getPosition()); + } + + void PhysicsSystem::insertActorPhysics(const MWWorld::Ptr& ptr, const std::string model){ + Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); + // std::cout << "Adding node with name" << node->getName(); + addActor (node->getName(), model, node->getPosition()); + } + } diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 7f7bfdcbb..a447d7bc1 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -4,6 +4,7 @@ #include #include #include +#include "ptr.hpp" namespace MWWorld { @@ -32,6 +33,11 @@ namespace MWWorld void scaleObject (const std::string& handle, float scale); bool toggleCollisionMode(); + std::pair getFacedHandle (MWWorld::World& world); + + void insertObjectPhysics(const MWWorld::Ptr& ptr, std::string model); + + void insertActorPhysics(const MWWorld::Ptr&, std::string model); private: OEngine::Render::OgreRenderer &mRender; diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index db950b00e..4eb41ebf5 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -22,7 +22,8 @@ namespace MWWorld playerPos[0] = playerPos[1] = playerPos[2] = 0; std::cout << renderer->getHandle(); - mPlayer.mData.setHandle (renderer->getHandle()); + + mPlayer.mData.setBaseNode(renderer->getNode()); /// \todo Do not make a copy of classes defined in esm/p records. mClass = new ESM::Class (*world.getStore().classes.find (player->cls)); } @@ -34,7 +35,7 @@ namespace MWWorld void Player::setPos(float x, float y, float z) { - /// \todo This fcuntion should be removed during the mwrender-refactoring. + /// \todo This fcuntion should be removed during the mwrender-refactoring. mWorld.moveObject (getPlayer(), x, y, z); } diff --git a/apps/openmw/mwworld/refdata.hpp b/apps/openmw/mwworld/refdata.hpp index 419bb2663..9a91a27b5 100644 --- a/apps/openmw/mwworld/refdata.hpp +++ b/apps/openmw/mwworld/refdata.hpp @@ -12,6 +12,7 @@ #include "../mwmechanics/movement.hpp" #include "containerstore.hpp" +#include namespace ESM { @@ -22,7 +23,8 @@ namespace MWWorld { class RefData { - std::string mHandle; + Ogre::SceneNode* mBaseNode; + MWScript::Locals mLocals; // if we find the overhead of heaving a locals // object in the refdata of refs without a script, @@ -43,16 +45,24 @@ namespace MWWorld ESM::Position mPosition; + public: /// @param cr Used to copy constant data such as position into this class where it can /// be altered without effecting the original data. This makes it possible /// to reset the position as the orignal data is still held in the CellRef - RefData(const ESMS::CellRef& cr) : mHasLocals (false), mEnabled (true), + RefData(const ESMS::CellRef& cr) : mBaseNode(0), mHasLocals (false), mEnabled (true), mCount (1), mPosition(cr.pos) {} + std::string getHandle() { - return mHandle; + return mBaseNode->getName(); + } + Ogre::SceneNode* getBaseNode(){ + return mBaseNode; + } + void setBaseNode(Ogre::SceneNode* base){ + mBaseNode = base; } int getCount() const @@ -69,10 +79,6 @@ namespace MWWorld } } - void setHandle (const std::string& handle) - { - mHandle = handle; - } void setCount (int count) { diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index da9bff6b2..b08a52aac 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -1,8 +1,6 @@ #include "scene.hpp" #include "world.hpp" -#include "../mwrender/interior.hpp" -#include "../mwrender/exterior.hpp" #include "../mwmechanics/mechanicsmanager.hpp" @@ -18,11 +16,13 @@ namespace { template -void insertCellRefList (T& cellRefList, ESMS::CellStore &cell) +void insertCellRefList(MWRender::RenderingManager& rendering, MWWorld::Environment& environment, + T& cellRefList, ESMS::CellStore &cell, MWWorld::PhysicsSystem& physics) { if (!cellRefList.list.empty()) { - //const MWWorld::Class& class_ = MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.list.begin(), &cell)); + const MWWorld::Class& class_ = + MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.list.begin(), &cell)); for (typename T::List::iterator it = cellRefList.list.begin(); it != cellRefList.list.end(); it++) @@ -30,11 +30,18 @@ void insertCellRefList (T& cellRefList, ESMS::CellStore &cell) if (it->mData.getCount() || it->mData.isEnabled()) { MWWorld::Ptr ptr (&*it, &cell); - /* TODO: call - * RenderingManager.insertObject - * class_.insertObjectPhysic - * class_.insertObjectMechanics - */ + + try + { + rendering.addObject(ptr); + class_.insertObject(ptr, physics, environment); + class_.enable (ptr, environment); + } + catch (const std::exception& e) + { + std::string error ("error during rendering: "); + std::cerr << error + e.what() << std::endl; + } } } } @@ -45,40 +52,57 @@ void insertCellRefList (T& cellRefList, ESMS::CellStore &cell) namespace MWWorld { - - void Scene::unloadCell (CellRenderCollection::iterator iter) + void Scene::advanceTime(){ + mRendering.addTime(); + } + void Scene::unloadCell (CellStoreCollection::iterator iter) { + std::cout << "Unloading cell\n"; ListHandles functor; - iter->first->forEach(functor); - { // silence annoying g++ warning - for (std::vector::const_iterator iter (functor.mHandles.begin()); - iter!=functor.mHandles.end(); ++iter) - mPhysics->removeObject (*iter); + MWWorld::Ptr::CellStore* active = *iter; + + + + + active->forEach(functor); + + { + + + // silence annoying g++ warning + for (std::vector::const_iterator iter (functor.mHandles.begin()); + iter!=functor.mHandles.end(); ++iter){ + Ogre::SceneNode* node = *iter; + mPhysics->removeObject (node->getName()); + } } - - mWorld->getLocalScripts().clearCell (iter->first); - - mEnvironment.mMechanicsManager->dropActors (iter->first); - mEnvironment.mSoundManager->stopSound (iter->first); - delete iter->second; - mActiveCells.erase (iter); + mRendering.removeCell(active); + //mPhysics->removeObject("Unnamed_43"); + mWorld->getLocalScripts().clearCell (active); + mEnvironment.mMechanicsManager->dropActors (active); + mEnvironment.mSoundManager->stopSound (active); + mActiveCells.erase(active); + } - void Scene::loadCell (Ptr::CellStore *cell, MWRender::CellRender *render) + void Scene::loadCell (Ptr::CellStore *cell) { // register local scripts mWorld->getLocalScripts().addCell (cell); - // This connects the cell data with the rendering scene. - std::pair result = - mActiveCells.insert (std::make_pair (cell, render)); - if (result.second) - { - // Load the cell and insert it into the renderer - result.first->second->show(); + + std::pair result = + mActiveCells.insert(cell); + if(result.second){ + insertCell(*cell, mEnvironment); + mRendering.cellAdded (cell); + mRendering.configureAmbient(*cell); + } + + } void Scene::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position, @@ -98,14 +122,14 @@ namespace MWWorld // remove active mEnvironment.mMechanicsManager->removeActor (mWorld->getPlayer().getPlayer()); - CellRenderCollection::iterator active = mActiveCells.begin(); + CellStoreCollection::iterator active = mActiveCells.begin(); while (active!=mActiveCells.end()) { - if (!(active->first->cell->data.flags & ESM::Cell::Interior)) + if (!((*active)->cell->data.flags & ESM::Cell::Interior)) { - if (std::abs (X-active->first->cell->data.gridX)<=1 && - std::abs (Y-active->first->cell->data.gridY)<=1) + if (std::abs (X-(*active)->cell->data.gridX)<=1 && + std::abs (Y-(*active)->cell->data.gridY)<=1) { // keep cells within the new 3x3 grid ++active; @@ -120,14 +144,14 @@ namespace MWWorld for (int x=X-1; x<=X+1; ++x) for (int y=Y-1; y<=Y+1; ++y) { - CellRenderCollection::iterator iter = mActiveCells.begin(); + CellStoreCollection::iterator iter = mActiveCells.begin(); while (iter!=mActiveCells.end()) { - assert (!(iter->first->cell->data.flags & ESM::Cell::Interior)); + assert (!((*iter)->cell->data.flags & ESM::Cell::Interior)); - if (x==iter->first->cell->data.gridX && - y==iter->first->cell->data.gridY) + if (x==(*iter)->cell->data.gridX && + y==(*iter)->cell->data.gridY) break; ++iter; @@ -137,19 +161,19 @@ namespace MWWorld { Ptr::CellStore *cell = mWorld->getExterior(x, y); - loadCell (cell, new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene, mPhysics)); + loadCell (cell); } } // find current cell - CellRenderCollection::iterator iter = mActiveCells.begin(); + CellStoreCollection::iterator iter = mActiveCells.begin(); while (iter!=mActiveCells.end()) { - assert (!(iter->first->cell->data.flags & ESM::Cell::Interior)); + assert (!((*iter)->cell->data.flags & ESM::Cell::Interior)); - if (X==iter->first->cell->data.gridX && - Y==iter->first->cell->data.gridY) + if (X==(*iter)->cell->data.gridX && + Y==(*iter)->cell->data.gridY) break; ++iter; @@ -157,7 +181,7 @@ namespace MWWorld assert (iter!=mActiveCells.end()); - mCurrentCell = iter->first; + mCurrentCell = *iter; // adjust player playerCellChange (mWorld->getExterior(X, Y), position, adjustPlayerPos); @@ -168,17 +192,15 @@ namespace MWWorld mCellChanged = true; } - Scene::Scene (Environment& environment, World *world, MWRender::MWScene& scene, PhysicsSystem *physics) - : mScene (scene), mCurrentCell (0), - mCellChanged (false), mEnvironment (environment), mWorld(world), mPhysics(physics) + //We need the ogre renderer and a scene node. + Scene::Scene (Environment& environment, World *world, MWRender::RenderingManager& rendering, PhysicsSystem *physics) + : mCurrentCell (0), mCellChanged (false), mEnvironment (environment), mWorld(world), + mPhysics(physics), mRendering(rendering) { } Scene::~Scene() { - for (CellRenderCollection::iterator iter (mActiveCells.begin()); - iter!=mActiveCells.end(); ++iter) - delete iter->second; } bool Scene::hasCellChanged() const @@ -186,15 +208,16 @@ namespace MWWorld return mCellChanged; } - const Scene::CellRenderCollection& Scene::getActiveCells() const + const Scene::CellStoreCollection& Scene::getActiveCells() const { return mActiveCells; } void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position) { + std::cout << "Changing to interior\n"; // remove active - CellRenderCollection::iterator active = mActiveCells.begin(); + CellStoreCollection::iterator active = mActiveCells.begin(); while (active!=mActiveCells.end()) { @@ -205,7 +228,7 @@ namespace MWWorld std::cout << "cellName:" << cellName << std::endl; Ptr::CellStore *cell = mWorld->getInterior(cellName); - loadCell (cell, new MWRender::InteriorCellRender (*cell, mEnvironment, mScene, mPhysics)); + loadCell (cell); // adjust player mCurrentCell = cell; @@ -215,7 +238,6 @@ namespace MWWorld mWorld->adjustSky(); mCellChanged = true; - //currentRegion->name = ""; } void Scene::changeToExteriorCell (const ESM::Position& position) @@ -238,36 +260,31 @@ namespace MWWorld mCellChanged = false; } -/*#include -#include -#include - -#include "../mwworld/class.hpp" -#include "../mwworld/ptr.hpp"*/ - -void Scene::insertCell(ESMS::CellStore &cell) +void Scene::insertCell(ESMS::CellStore &cell, + MWWorld::Environment& environment) { // Loop through all references in the cell - insertCellRefList (cell.activators, cell); - insertCellRefList (cell.potions, cell); - insertCellRefList (cell.appas, cell); - insertCellRefList (cell.armors, cell); - insertCellRefList (cell.books, cell); - insertCellRefList (cell.clothes, cell); - insertCellRefList (cell.containers, cell); - insertCellRefList (cell.creatures, cell); - insertCellRefList (cell.doors, cell); - insertCellRefList (cell.ingreds, cell); - insertCellRefList (cell.creatureLists, cell); - insertCellRefList (cell.itemLists, cell); - insertCellRefList (cell.lights, cell); - insertCellRefList (cell.lockpicks, cell); - insertCellRefList (cell.miscItems, cell); - insertCellRefList (cell.npcs, cell); - insertCellRefList (cell.probes, cell); - insertCellRefList (cell.repairs, cell); - insertCellRefList (cell.statics, cell); - insertCellRefList (cell.weapons, cell); + insertCellRefList(mRendering, environment, cell.activators, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.potions, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.appas, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.armors, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.books, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.clothes, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.containers, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.creatures, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.doors, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.ingreds, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.creatureLists, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.itemLists, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.lights, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.lockpicks, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.miscItems, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.npcs, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.probes, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.repairs, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.statics, cell, *mPhysics); + insertCellRefList(mRendering, environment, cell.weapons, cell, *mPhysics); } + } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 9e43a98a5..d3df7c0f5 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -6,17 +6,18 @@ #include +#include + #include -#include "../mwrender/mwscene.hpp" -#include "physicssystem.hpp" +#include "../mwrender/renderingmanager.hpp" +#include "../mwrender/renderinginterface.hpp" +#include "physicssystem.hpp" #include "refdata.hpp" #include "ptr.hpp" #include "globals.hpp" -#include - namespace Ogre { class Vector3; @@ -53,29 +54,32 @@ namespace MWWorld public: - typedef std::map CellRenderCollection; + typedef std::set CellStoreCollection; private: - MWRender::MWScene& mScene; - Ptr::CellStore *mCurrentCell; // the cell, the player is in - CellRenderCollection mActiveCells; + //OEngine::Render::OgreRenderer& mRenderer; + Ptr::CellStore* mCurrentCell; // the cell, the player is in + CellStoreCollection mActiveCells; bool mCellChanged; Environment& mEnvironment; World *mWorld; PhysicsSystem *mPhysics; + MWRender::RenderingManager& mRendering; void playerCellChange (Ptr::CellStore *cell, const ESM::Position& position, bool adjustPlayerPos = true); + + public: - Scene (Environment& environment, World *world, MWRender::MWScene& scene, PhysicsSystem *physics); + Scene (Environment& environment, World *world, MWRender::RenderingManager& rendering, PhysicsSystem *physics); ~Scene(); - void unloadCell (CellRenderCollection::iterator iter); + void unloadCell (CellStoreCollection::iterator iter); - void loadCell (Ptr::CellStore *cell, MWRender::CellRender *render); + void loadCell (Ptr::CellStore *cell); void changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos); ///< Move from exterior to interior or from interior cell to a different @@ -83,7 +87,7 @@ namespace MWWorld Ptr::CellStore* getCurrentCell (); - const CellRenderCollection& getActiveCells () const; + const CellStoreCollection& getActiveCells () const; bool hasCellChanged() const; ///< Has the player moved to a different cell, since the last frame? @@ -96,9 +100,8 @@ namespace MWWorld void markCellAsUnchanged(); -// std::string getFacedHandle(); - - void insertCell(ESMS::CellStore &cell); + void insertCell(ESMS::CellStore &cell, MWWorld::Environment& environment); + void advanceTime(); }; } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index ff530454f..2232e8a1d 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -7,8 +7,7 @@ #include #include "../mwrender/sky.hpp" -#include "../mwrender/interior.hpp" -#include "../mwrender/exterior.hpp" +#include "../mwrender/player.hpp" #include "../mwmechanics/mechanicsmanager.hpp" @@ -54,12 +53,13 @@ namespace for (iterator iter (refList.list.begin()); iter!=refList.list.end(); ++iter) { + if(iter->mData.getBaseNode()){ if (iter->mData.getHandle()==handle) { return &*iter; } + } } - return 0; } } @@ -71,75 +71,46 @@ namespace MWWorld if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.activators)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.potions)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.appas)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.armors)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.books)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.clothes)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.containers)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.creatures)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.doors)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.ingreds)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.lights)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.lockpicks)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.miscItems)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.npcs)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.probes)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.repairs)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.statics)) return Ptr (ref, &cell); - if (ESMS::LiveCellRef *ref = searchViaHandle (handle, cell.weapons)) return Ptr (ref, &cell); - return Ptr(); } - MWRender::CellRender *World::searchRender (Ptr::CellStore *store) - { - Scene::CellRenderCollection::const_iterator iter = mWorldScene->getActiveCells().find (store); - - if (iter!=mWorldScene->getActiveCells().end()) - { - return iter->second; - } - - return 0; - } int World::getDaysPerMonth (int month) const { @@ -176,7 +147,7 @@ namespace MWWorld const Files::Collections& fileCollections, const std::string& master, const boost::filesystem::path& resDir, bool newGame, Environment& environment, const std::string& encoding) - : mScene (renderer,physEng), mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), + : mRendering (renderer,resDir, physEng, environment),mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), mSky (false), mEnvironment (environment), mNextDynamicRecord (0), mCells (mStore, mEsm, *this) { mPhysEngine = physEng; @@ -192,7 +163,8 @@ namespace MWWorld mEsm.open (masterPath.string()); mStore.load (mEsm); - mPlayer = new MWWorld::Player (mScene.getPlayer(), mStore.npcs.find ("player"), *this); + MWRender::Player* play = &(mRendering.getPlayer()); + mPlayer = new MWWorld::Player (play, mStore.npcs.find ("player"), *this); mPhysics->addActor (mPlayer->getPlayer().getRefData().getHandle(), "", Ogre::Vector3 (0, 0, 0)); // global variables @@ -206,18 +178,18 @@ namespace MWWorld mPhysEngine = physEng; - mWorldScene = new Scene(environment, this, mScene, mPhysics); - mRenderingManager = new MWRender::RenderingManager( - MWRender::SkyManager::create(renderer.getWindow(), mScene.getCamera(), resDir) - ); + mWorldScene = new Scene(environment, this, mRendering, mPhysics); + } World::~World() { delete mWorldScene; delete mGlobalVariables; - delete mPlayer; + delete mPhysics; + + delete mPlayer; } const ESM::Cell *World::getExterior (const std::string& cellName) const @@ -303,10 +275,11 @@ namespace MWWorld } // active cells - for (Scene::CellRenderCollection::const_iterator iter (mWorldScene->getActiveCells().begin()); + for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin()); iter!=mWorldScene->getActiveCells().end(); ++iter) { - Ptr ptr = mCells.getPtr (name, *iter->first); + Ptr::CellStore* cellstore = *iter; + Ptr ptr = mCells.getPtr (name, *cellstore); if (!ptr.isEmpty()) return ptr; @@ -327,11 +300,11 @@ namespace MWWorld { if (mPlayer->getPlayer().getRefData().getHandle()==handle) return mPlayer->getPlayer(); - - for (Scene::CellRenderCollection::const_iterator iter (mWorldScene->getActiveCells().begin()); + for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin()); iter!=mWorldScene->getActiveCells().end(); ++iter) { - Ptr ptr = getPtrViaHandle (handle, *iter->first); + Ptr::CellStore* cellstore = *iter; + Ptr ptr = getPtrViaHandle (handle, *cellstore); if (!ptr.isEmpty()) return ptr; @@ -346,13 +319,12 @@ namespace MWWorld { reference.getRefData().enable(); - if (MWRender::CellRender *render = searchRender (reference.getCell())) - { - render->enable (reference.getRefData().getHandle()); - if (mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end()) - Class::get (reference).enable (reference, mEnvironment); - } + //render->enable (reference.getRefData().getHandle()); + if(mWorldScene->getActiveCells().find (reference.getCell()) != mWorldScene->getActiveCells().end()) + Class::get (reference).enable (reference, mEnvironment); + + } } @@ -362,29 +334,28 @@ namespace MWWorld { reference.getRefData().disable(); - if (MWRender::CellRender *render = searchRender (reference.getCell())) - { - render->disable (reference.getRefData().getHandle()); - if (mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end()) - { - Class::get (reference).disable (reference, mEnvironment); - mEnvironment.mSoundManager->stopSound3D (reference); - } + //render->disable (reference.getRefData().getHandle()); + if(mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end()){ + Class::get (reference).disable (reference, mEnvironment); + mEnvironment.mSoundManager->stopSound3D (reference); } + + } } void World::advanceTime (double hours) { hours += mGlobalVariables->getFloat ("gamehour"); - + setHour (hours); int days = hours / 24; if (days>0) mGlobalVariables->setInt ("dayspassed", days + mGlobalVariables->getInt ("dayspassed")); + mWorldScene->advanceTime(); } void World::setHour (double hour) @@ -398,7 +369,7 @@ namespace MWWorld mGlobalVariables->setFloat ("gamehour", hour); - mRenderingManager->skySetHour (hour); + mRendering.skySetHour (hour); if (days>0) setDay (days + mGlobalVariables->getInt ("day")); @@ -433,7 +404,7 @@ namespace MWWorld mGlobalVariables->setInt ("day", day); mGlobalVariables->setInt ("month", month); - mRenderingManager->skySetDate (day, month); + mRendering.skySetDate (day, month); } void World::setMonth (int month) @@ -454,7 +425,7 @@ namespace MWWorld if (years>0) mGlobalVariables->setInt ("year", years+mGlobalVariables->getInt ("year")); - mRenderingManager->skySetDate (mGlobalVariables->getInt ("day"), month); + mRendering.skySetDate (mGlobalVariables->getInt ("day"), month); } bool World::toggleSky() @@ -462,34 +433,34 @@ namespace MWWorld if (mSky) { mSky = false; - mRenderingManager->skyDisable(); + mRendering.skyDisable(); return false; } else { mSky = true; // TODO check for extorior or interior with sky. - mRenderingManager->skySetHour (mGlobalVariables->getFloat ("gamehour")); - mRenderingManager->skySetDate (mGlobalVariables->getInt ("day"), + mRendering.skySetHour (mGlobalVariables->getFloat ("gamehour")); + mRendering.skySetDate (mGlobalVariables->getInt ("day"), mGlobalVariables->getInt ("month")); - mRenderingManager->skyEnable(); + mRendering.skyEnable(); return true; } } int World::getMasserPhase() const { - return mRenderingManager->skyGetMasserPhase(); + return mRendering.skyGetMasserPhase(); } int World::getSecundaPhase() const { - return mRenderingManager->skyGetSecundaPhase(); + return mRendering.skyGetSecundaPhase(); } void World::setMoonColour (bool red) { - mRenderingManager->skySetMoonColour (red); + mRendering.skySetMoonColour (red); } float World::getTimeScaleFactor() const @@ -514,7 +485,7 @@ namespace MWWorld std::string World::getFacedHandle() { - std::pair result = mScene.getFacedHandle (*this); + std::pair result = mPhysics->getFacedHandle (*this); if (result.first.empty() || result.second>getStore().gameSettings.find ("iMaxActivateDist")->i) @@ -529,21 +500,16 @@ namespace MWWorld { ptr.getRefData().setCount (0); - if (MWRender::CellRender *render = searchRender (ptr.getCell())) - { - if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end()) - { - Class::get (ptr).disable (ptr, mEnvironment); - mEnvironment.mSoundManager->stopSound3D (ptr); - mPhysics->removeObject (ptr.getRefData().getHandle()); + if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end()){ +// Class::get (ptr).disable (ptr, mEnvironment); /// \todo this line needs to be removed + mEnvironment.mSoundManager->stopSound3D (ptr); - mLocalScripts.remove (ptr); + mPhysics->removeObject (ptr.getRefData().getHandle()); + mRendering.removeObject(ptr); + + mLocalScripts.remove (ptr); } - - render->deleteObject (ptr.getRefData().getHandle()); - ptr.getRefData().setHandle (""); - } } } @@ -575,11 +541,9 @@ namespace MWWorld } } - // \todo cell change for non-player ref + /// \todo cell change for non-player ref - // \todo this should go into the new scene class and eventually into the objects/actors classes. - mScene.getMgr()->getSceneNode (ptr.getRefData().getHandle())-> - setPosition (Ogre::Vector3 (x, y, z)); + mRendering.moveObject (ptr, Ogre::Vector3 (x, y, z)); } void World::moveObject (Ptr ptr, float x, float y, float z) @@ -653,7 +617,7 @@ namespace MWWorld bool World::toggleRenderMode (RenderMode mode) { - return mScene.toggleRenderMode (mode); + return mRendering.toggleRenderMode (mode); } std::pair World::createRecord (const ESM::Potion& record) @@ -710,4 +674,21 @@ namespace MWWorld return cell; } } + + void World::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, + int number) + { + mRendering.playAnimationGroup (ptr, groupName, mode, number); + } + + void World::skipAnimation (const MWWorld::Ptr& ptr) + { + mRendering.skipAnimation (ptr); + } + void World::setObjectPhysicsRotation(const std::string& handle, Ogre::Quaternion quat){ + mPhysics->rotateObject(handle, quat); + } + void World::setObjectPhysicsPosition(const std::string& handle, Ogre::Vector3 vec){ + mPhysics->moveObject(handle, vec); + } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 978f14c8e..235d203a6 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -8,8 +8,8 @@ #include -#include "../mwrender/mwscene.hpp" -#include "../mwrender/rendering_manager.hpp" +#include "../mwrender/debugging.hpp" +#include "../mwrender/renderingmanager.hpp" #include "refdata.hpp" #include "ptr.hpp" @@ -65,7 +65,8 @@ namespace MWWorld private: - MWRender::MWScene mScene; + MWRender::RenderingManager mRendering; + MWWorld::Scene *mWorldScene; MWWorld::Player *mPlayer; ESM::ESMReader mEsm; @@ -75,7 +76,6 @@ namespace MWWorld MWWorld::PhysicsSystem *mPhysics; bool mSky; Environment& mEnvironment; - MWRender::RenderingManager *mRenderingManager; int mNextDynamicRecord; Cells mCells; @@ -88,7 +88,6 @@ namespace MWWorld Ptr getPtrViaHandle (const std::string& handle, Ptr::CellStore& cellStore); - MWRender::CellRender *searchRender (Ptr::CellStore *store); int getDaysPerMonth (int month) const; @@ -134,8 +133,10 @@ namespace MWWorld Ptr getPtrViaHandle (const std::string& handle); ///< Return a pointer to a liveCellRef with the given Ogre handle. + /// \todo enable reference in the OGRE scene void enable (Ptr reference); + /// \todo 5disable reference in the OGRE scene void disable (Ptr reference); void advanceTime (double hours); @@ -205,6 +206,20 @@ namespace MWWorld const ESM::Cell *createRecord (const ESM::Cell& record); ///< Create a new recrod (of type cell) in the ESM store. /// \return ID, pointer to created record + + void playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, + int number = 1); + ///< Run animation for a MW-reference. Calls to this function for references that are + /// currently not in the rendered scene should be ignored. + /// + /// \param mode: 0 normal, 1 immediate start, 2 immediate loop + /// \param number How offen the animation should be run + + void skipAnimation (const MWWorld::Ptr& ptr); + ///< Skip the animation for the given MW-reference for one frame. Calls to this function for + /// references that are currently not in the rendered scene should be ignored. + void setObjectPhysicsRotation(const std::string& handle,Ogre::Quaternion quat); + void setObjectPhysicsPosition(const std::string& handle,Ogre::Vector3 vector); }; } diff --git a/components/bsa/bsa_archive.cpp b/components/bsa/bsa_archive.cpp index 2178be318..72d15944d 100644 --- a/components/bsa/bsa_archive.cpp +++ b/components/bsa/bsa_archive.cpp @@ -240,15 +240,36 @@ public: // should not have been declared const in the first place. BSAFile *narc = (BSAFile*)&arc; + String passed = filename; + if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<' + || filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':' + || filename.at(filename.length() - 1) == '|') + { + passed = filename.substr(0, filename.length() - 2); + } + if(filename.at(filename.length() - 2) == '>') + passed = filename.substr(0, filename.length() - 6); // Open the file - StreamPtr strm = narc->getFile(filename.c_str()); + StreamPtr strm = narc->getFile(passed.c_str()); // Wrap it into an Ogre::DataStream. return DataStreamPtr(new Mangle2OgreStream(strm)); } // Check if the file exists. - bool exists(const String& filename) { return arc.exists(filename.c_str()); } + bool exists(const String& filename) { + String passed = filename; + if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<' + || filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':' + || filename.at(filename.length() - 1) == '|') + { + passed = filename.substr(0, filename.length() - 2); + } + if(filename.at(filename.length() - 2) == '>') + passed = filename.substr(0, filename.length() - 6); + +return arc.exists(passed.c_str()); +} time_t getModifiedTime(const String&) { return 0; } // This is never called as far as I can see. diff --git a/components/esm_store/cell_store.hpp b/components/esm_store/cell_store.hpp index 12f644417..d064312f1 100644 --- a/components/esm_store/cell_store.hpp +++ b/components/esm_store/cell_store.hpp @@ -187,7 +187,7 @@ namespace ESMS ++iter) if (!functor (iter->ref, iter->mData)) return false; - + return true; } diff --git a/components/nif/data.hpp b/components/nif/data.hpp index c483b4873..9e28e1534 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -26,6 +26,7 @@ #include "controlled.hpp" #include +#include namespace Nif { @@ -366,6 +367,12 @@ public: Vector trans; // Translation float scale; // Probably scale (always 1) }; + struct BoneTrafoCopy + { + Ogre::Quaternion rotation; + Ogre::Vector3 trans; + float scale; + }; struct VertWeight { @@ -380,6 +387,19 @@ public: const Vector4 *unknown; Misc::SliceArray weights; }; + struct BoneInfoCopy + { + std::string bonename; + unsigned short bonehandle; + BoneTrafoCopy trafo; + Vector4 unknown; + //std::vector weights; + }; + struct IndividualWeight + { + float weight; + unsigned int boneinfocopyindex; + }; const BoneTrafo *trafo; std::vector bones; @@ -412,92 +432,396 @@ public: class NiMorphData : public Record { + float startTime; + float stopTime; + std::vector initialVertices; + std::vector > relevantTimes; + std::vector > relevantData; + std::vector > additionalVertices; + + public: - void read(NIFFile *nif) + float getStartTime(){ + return startTime; + } + float getStopTime(){ + return stopTime; + } + void setStartTime(float time){ + startTime = time; + } + + void setStopTime(float time){ + stopTime = time; + } + std::vector getInitialVertices(){ + return initialVertices; + } + std::vector > getRelevantData(){ + return relevantData; + } + std::vector > getRelevantTimes(){ + return relevantTimes; + } + std::vector > getAdditionalVertices(){ + return additionalVertices; + } + +void read(NIFFile *nif) { int morphCount = nif->getInt(); int vertCount = nif->getInt(); nif->getByte(); + int magic = nif->getInt(); + int type = nif->getInt(); + for(int i = 0; i < vertCount; i++){ - for(int i=0; igetInt(); - nif->getInt(); - if(magic) - // Time, data, forward, backward tangents - nif->getFloatLen(4*magic); - - nif->getFloatLen(vertCount*3); + float x = nif->getFloat(); + float y = nif->getFloat(); + float z = nif->getFloat(); + initialVertices.push_back(Ogre::Vector3(x, y, z)); + } + + for(int i=1; igetInt(); + type = nif->getInt(); + std::vector current; + std::vector currentTime; + for(int i = 0; i < magic; i++){ + // Time, data, forward, backward tangents + float time = nif->getFloat(); + float x = nif->getFloat(); + float y = nif->getFloat(); + float z = nif->getFloat(); + current.push_back(Ogre::Vector3(x,y,z)); + currentTime.push_back(time); + //nif->getFloatLen(4*magic); + } + if(magic){ + relevantData.push_back(current); + relevantTimes.push_back(currentTime); + } + std::vector verts; + for(int i = 0; i < vertCount; i++){ + float x = nif->getFloat(); + float y = nif->getFloat(); + float z = nif->getFloat(); + verts.push_back(Ogre::Vector3(x, y, z)); + } + additionalVertices.push_back(verts); } } }; + class NiKeyframeData : public Record { - public: + std::string bonename; + //Rotations + std::vector quats; + std::vector tbc; + std::vector rottime; + float startTime; + float stopTime; + int rtype; - void read(NIFFile *nif) - { - // Rotations first - int count = nif->getInt(); - if(count) - { - int type = nif->getInt(); + //Translations + std::vector translist1; + std::vector translist2; + std::vector translist3; + std::vector transtbc; + std::vector transtime; + int ttype; - if(type == 1) - nif->skip(count*4*5); // time + quaternion - else if(type == 3) - nif->skip(count*4*8); // rot1 + tension+bias+continuity - else if(type == 4) - { - for(int j=0;jgetFloat(); // time - for(int i=0; i<3; i++) - { - int cnt = nif->getInt(); - int type = nif->getInt(); - if(type == 1) - nif->skip(cnt*4*2); // time + unknown - else if(type == 2) - nif->skip(cnt*4*4); // time + unknown vector - else nif->fail("Unknown sub-rotation type"); - } - } - } - else nif->fail("Unknown rotation type in NiKeyframeData"); - } + //Scalings - // Then translation - count = nif->getInt(); + std::vector scalefactor; + std::vector scaletime; + std::vector forwards; + std::vector backwards; + std::vector tbcscale; + int stype; - if(count) - { - int type = nif->getInt(); + + +public: + void clone(NiKeyframeData c) + { + quats = c.getQuat(); + tbc = c.getrTbc(); + rottime = c.getrTime(); - if(type == 1) - nif->getFloatLen(count*4); // time + translation - else if(type == 2) - nif->getFloatLen(count*10); // trans1 + forward + backward - else if(type == 3) - nif->getFloatLen(count*7); // trans1 + tension,bias,continuity - else nif->fail("Unknown translation type"); - } + //types + ttype = c.getTtype(); + rtype = c.getRtype(); + stype = c.getStype(); + + + translist1 = c.getTranslist1(); + translist2 = c.getTranslist2(); + translist3 = c.getTranslist3(); + + transtime = c.gettTime(); + + bonename = c.getBonename(); + + + } + + void setBonename(std::string bone) + { + bonename = bone; + } + void setStartTime(float start) + { + startTime = start; + } + void setStopTime(float end) + { + stopTime = end; + } + void read(NIFFile *nif) + { + // Rotations first + int count = nif->getInt(); + //std::vector quat(count); + //std::vector rottime(count); + if(count) + { + + //TYPE1 LINEAR_KEY + //TYPE2 QUADRATIC_KEY + //TYPE3 TBC_KEY + //TYPE4 XYZ_ROTATION_KEY + //TYPE5 UNKNOWN_KEY + rtype = nif->getInt(); + //std::cout << "Count: " << count << "Type: " << type << "\n"; + + if(rtype == 1) + { + //We need to actually read in these values instead of skipping them + //nif->skip(count*4*5); // time + quaternion + for (int i = 0; i < count; i++) { + float time = nif->getFloat(); + float w = nif->getFloat(); + float x = nif->getFloat(); + float y = nif->getFloat(); + float z = nif->getFloat(); + Ogre::Quaternion quat = Ogre::Quaternion(Ogre::Real(w), Ogre::Real(x), Ogre::Real(y), Ogre::Real(z)); + quats.push_back(quat); + rottime.push_back(time); + //if(time == 0.0 || time > 355.5) + // std::cout <<"Time:" << time << "W:" << w <<"X:" << x << "Y:" << y << "Z:" << z << "\n"; + } + } + else if(rtype == 3) + { //Example - node 116 in base_anim.nif + for (int i = 0; i < count; i++) { + float time = nif->getFloat(); + float w = nif->getFloat(); + float x = nif->getFloat(); + float y = nif->getFloat(); + float z = nif->getFloat(); + + float tbcx = nif->getFloat(); + float tbcy = nif->getFloat(); + float tbcz = nif->getFloat(); + Ogre::Quaternion quat = Ogre::Quaternion(Ogre::Real(w), Ogre::Real(x), Ogre::Real(y), Ogre::Real(z)); + Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz); + quats.push_back(quat); + rottime.push_back(time); + tbc.push_back(vec); + //if(time == 0.0 || time > 355.5) + // std::cout <<"Time:" << time << "W:" << w <<"X:" << x << "Y:" << y << "Z:" << z << "\n"; + } + + //nif->skip(count*4*8); // rot1 + tension+bias+continuity + } + else if(rtype == 4) + { + for(int j=0;jgetFloat(); // time + for(int i=0; i<3; i++) + { + int cnt = nif->getInt(); + int type = nif->getInt(); + if(type == 1) + nif->skip(cnt*4*2); // time + unknown + else if(type == 2) + nif->skip(cnt*4*4); // time + unknown vector + else nif->fail("Unknown sub-rotation type"); + } + } + } + else nif->fail("Unknown rotation type in NiKeyframeData"); + } + //first = false; + + // Then translation + count = nif->getInt(); + + if(count) + { + ttype = nif->getInt(); + + //std::cout << "TransCount:" << count << " Type: " << type << "\n"; + if(ttype == 1) { + for (int i = 0; i < count; i++) { + float time = nif->getFloat(); + float x = nif->getFloat(); + float y = nif->getFloat(); + float z = nif->getFloat(); + Ogre::Vector3 trans = Ogre::Vector3(x, y, z); + translist1.push_back(trans); + transtime.push_back(time); + } + //nif->getFloatLen(count*4); // time + translation + } + else if(ttype == 2) + { //Example - node 116 in base_anim.nif + for (int i = 0; i < count; i++) { + float time = nif->getFloat(); + float x = nif->getFloat(); + float y = nif->getFloat(); + float z = nif->getFloat(); + float x2 = nif->getFloat(); + float y2 = nif->getFloat(); + float z2 = nif->getFloat(); + float x3 = nif->getFloat(); + float y3 = nif->getFloat(); + float z3 = nif->getFloat(); + Ogre::Vector3 trans = Ogre::Vector3(x, y, z); + Ogre::Vector3 trans2 = Ogre::Vector3(x2, y2, z2); + Ogre::Vector3 trans3 = Ogre::Vector3(x3, y3, z3); + transtime.push_back(time); + translist1.push_back(trans); + translist2.push_back(trans2); + translist3.push_back(trans3); + } + + //nif->getFloatLen(count*10); // trans1 + forward + backward + } + else if(ttype == 3){ + for (int i = 0; i < count; i++) { + float time = nif->getFloat(); + float x = nif->getFloat(); + float y = nif->getFloat(); + float z = nif->getFloat(); + float t = nif->getFloat(); + float b = nif->getFloat(); + float c = nif->getFloat(); + Ogre::Vector3 trans = Ogre::Vector3(x, y, z); + Ogre::Vector3 tbc = Ogre::Vector3(t, b, c); + translist1.push_back(trans); + transtbc.push_back(tbc); + transtime.push_back(time); + } + //nif->getFloatLen(count*7); // trans1 + tension,bias,continuity + } + else nif->fail("Unknown translation type"); + } + + // Finally, scalings + count = nif->getInt(); + if(count) + { + stype = nif->getInt(); + + + for(int i = 0; i < count; i++){ + + + //int size = 0; + if(stype >= 1 && stype < 4) + { + float time = nif->getFloat(); + float scale = nif->getFloat(); + scaletime.push_back(time); + scalefactor.push_back(scale); + //size = 2; // time+scale + } + else nif->fail("Unknown scaling type"); + if(stype == 2){ + //size = 4; // 1 + forward + backward (floats) + float forward = nif->getFloat(); + float backward = nif->getFloat(); + forwards.push_back(forward); + backwards.push_back(backward); + } + else if(stype == 3){ + float tbcx = nif->getFloat(); + float tbcy = nif->getFloat(); + float tbcz = nif->getFloat(); + Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz); + tbcscale.push_back(vec); + + //size = 5; // 1 + tbc + } + + } + } + else + stype = 0; + } + int getRtype(){ + return rtype; + } + int getStype(){ + return stype; + } + int getTtype(){ + return ttype; + } + float getStartTime(){ + return startTime; + } + float getStopTime(){ + return stopTime; + } + std::vector getQuat(){ + return quats; + } + std::vector getrTbc(){ + return tbc; + } + std::vector getrTime(){ + return rottime; + } + + std::vector getTranslist1(){ + return translist1; + } + std::vector getTranslist2(){ + return translist2; + } + std::vector getTranslist3(){ + return translist3; + } + std::vector gettTime(){ + return transtime; + } + std::vector getScalefactor(){ + return scalefactor; + } + std::vector getForwards(){ + return forwards; + } + std::vector getBackwards(){ + return backwards; + } + std::vector getScaleTbc(){ + return tbcscale; + } + + std::vector getsTime(){ + return scaletime; + } + std::string getBonename(){ return bonename; + } - // Finally, scalings - count = nif->getInt(); - if(count) - { - int type = nif->getInt(); - int size = 0; - if(type == 1) size = 2; // time+scale - else if(type == 2) size = 4; // 1 + forward + backward (floats) - else if(type == 3) size = 5; // 1 + tbc - else nif->fail("Unknown scaling type"); - nif->getFloatLen(count*size); - } - } }; } // Namespace diff --git a/components/nif/node.hpp b/components/nif/node.hpp index f0ad54655..080042746 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -93,6 +93,20 @@ public: } }; +struct NiTriShapeCopy +{ + std::string sname; + std::vector boneSequence; + Nif::NiSkinData::BoneTrafoCopy trafo; + //Ogre::Quaternion initialBoneRotation; + //Ogre::Vector3 initialBoneTranslation; + std::vector vertices; + std::vector normals; + std::vector boneinfo; + std::map > vertsToWeights; + Nif::NiMorphData morph; +}; + struct NiNode : Node { NodeList children; @@ -133,6 +147,27 @@ struct NiTriShape : Node data.read(nif); skin.read(nif); } + + NiTriShapeCopy clone(){ + NiTriShapeCopy copy; + copy.sname = name.toString(); + float *ptr = (float*)data->vertices.ptr; + float *ptrNormals = (float*)data->normals.ptr; + int numVerts = data->vertices.length / 3; + for(int i = 0; i < numVerts; i++) + { + float *current = (float*) (ptr + i * 3); + copy.vertices.push_back(Ogre::Vector3(*current, *(current + 1), *(current + 2))); + + if(ptrNormals){ + float *currentNormals = (float*) (ptrNormals + i * 3); + copy.normals.push_back(Ogre::Vector3(*currentNormals, *(currentNormals + 1), *(currentNormals + 2))); + } + } + + + return copy; + } }; struct NiCamera : Node @@ -186,5 +221,7 @@ struct NiRotatingParticles : Node } }; + + } // Namespace #endif diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 668fdcceb..c62f59ea3 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -24,25 +24,7 @@ //loadResource->handleNode->handleNiTriShape->createSubMesh #include "ogre_nif_loader.hpp" -#include -#include -#include -#include "../nif/nif_file.hpp" -#include "../nif/node.hpp" -#include "../nif/data.hpp" -#include "../nif/property.hpp" -#include "../nif/controller.hpp" -#include "../nif/extra.hpp" -#include - -#include -#include -// For warning messages -#include - -// float infinity -#include typedef unsigned char ubyte; @@ -219,6 +201,12 @@ static CompareFunction getTestMode(int mode) } */ +void NIFLoader::setOutputAnimFiles(bool output){ + mOutputAnimFiles = output; +} +void NIFLoader::setVerbosePath(std::string path){ + verbosePath = path; +} void NIFLoader::createMaterial(const String &name, const Vector &ambient, const Vector &diffuse, @@ -230,11 +218,24 @@ void NIFLoader::createMaterial(const String &name, { MaterialPtr material = MaterialManager::getSingleton().create(name, resourceGroup); + + //Hardware Skinning code, textures may be the wrong color if enabled + /*if(!mSkel.isNull()){ + material->removeAllTechniques(); + + Ogre::Technique* tech = material->createTechnique(); + //tech->setSchemeName("blahblah"); + Pass* pass = tech->createPass(); + pass->setVertexProgram("Ogre/HardwareSkinningFourWeights"); + }*/ + // This assigns the texture to this material. If the texture name is // a file name, and this file exists (in a resource directory), it // will automatically be loaded when needed. If not (such as for // internal NIF textures that we might support later), we should // already have inserted a manual loader for the texture. + + if (!texName.empty()) { Pass *pass = material->getTechnique(0)->getPass(0); @@ -294,6 +295,8 @@ void NIFLoader::createMaterial(const String &name, material->setSpecular(specular.array[0], specular.array[1], specular.array[2], alpha); material->setSelfIllumination(emissive.array[0], emissive.array[1], emissive.array[2]); material->setShininess(glossiness); + + } // Takes a name and adds a unique part to it. This is just used to @@ -355,20 +358,69 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( VertexElement::getTypeSize(VET_FLOAT3), - numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); - vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, true); + numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); + + if(flip) + { + float *datamod = new float[data->vertices.length]; + //std::cout << "Shape" << shape->name.toString() << "\n"; + for(int i = 0; i < numVerts; i++) + { + int index = i * 3; + const float *pos = data->vertices.ptr + index; + Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2)); + original = mTransform * original; + mBoundingBox.merge(original); + datamod[index] = original.x; + datamod[index+1] = original.y; + datamod[index+2] = original.z; + } + vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false); + } + else + { + vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, false); + } + VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding; bind->setBinding(nextBuf++, vbuf); - // Vertex normals if (data->normals.length) { decl->addElement(nextBuf, 0, VET_FLOAT3, VES_NORMAL); vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( VertexElement::getTypeSize(VET_FLOAT3), - numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); - vbuf->writeData(0, vbuf->getSizeInBytes(), data->normals.ptr, true); + numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); + + if(flip) + { + Quaternion rotation = mTransform.extractQuaternion(); + rotation.normalise(); + + float *datamod = new float[data->normals.length]; + for(int i = 0; i < numVerts; i++) + { + int index = i * 3; + const float *pos = data->normals.ptr + index; + Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2)); + original = rotation * original; + if (mNormaliseNormals) + { + original.normalise(); + } + + + datamod[index] = original.x; + datamod[index+1] = original.y; + datamod[index+2] = original.z; + } + vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false); + } + else + { + vbuf->writeData(0, vbuf->getSizeInBytes(), data->normals.ptr, false); + } bind->setBinding(nextBuf++, vbuf); } @@ -393,30 +445,79 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std bind->setBinding(nextBuf++, vbuf); } - // Texture UV coordinates - if (data->uvlist.length) + if (data->uvlist.length) { + decl->addElement(nextBuf, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES); vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( VertexElement::getTypeSize(VET_FLOAT2), - numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); + numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY,false); - vbuf->writeData(0, vbuf->getSizeInBytes(), data->uvlist.ptr, true); + if(flip) + { + float *datamod = new float[data->uvlist.length]; + + for(unsigned int i = 0; i < data->uvlist.length; i+=2){ + float x = *(data->uvlist.ptr + i); + + float y = *(data->uvlist.ptr + i + 1); + + datamod[i] =x; + datamod[i + 1] =y; + } + vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false); + } + else + vbuf->writeData(0, vbuf->getSizeInBytes(), data->uvlist.ptr, false); bind->setBinding(nextBuf++, vbuf); } - // Triangle faces + // Triangle faces - The total number of triangle points int numFaces = data->triangles.length; + if (numFaces) { + + sub->indexData->indexCount = numFaces; + sub->indexData->indexStart = 0; HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton(). createIndexBuffer(HardwareIndexBuffer::IT_16BIT, numFaces, - HardwareBuffer::HBU_STATIC_WRITE_ONLY); - ibuf->writeData(0, ibuf->getSizeInBytes(), data->triangles.ptr, true); + HardwareBuffer::HBU_STATIC_WRITE_ONLY, true); + + if(flip && mFlipVertexWinding && sub->indexData->indexCount % 3 == 0){ + + sub->indexData->indexBuffer = ibuf; + + uint16 *datamod = new uint16[numFaces]; + int index = 0; + for (size_t i = 0; i < sub->indexData->indexCount; i+=3) + { + + const short *pos = data->triangles.ptr + index; + uint16 i0 = (uint16) *(pos+0); + uint16 i1 = (uint16) *(pos+1); + uint16 i2 = (uint16) *(pos+2); + + //std::cout << "i0: " << i0 << "i1: " << i1 << "i2: " << i2 << "\n"; + + + datamod[index] = i2; + datamod[index+1] = i1; + datamod[index+2] = i0; + + index += 3; + } + + ibuf->writeData(0, ibuf->getSizeInBytes(), datamod, false); + + } + else + ibuf->writeData(0, ibuf->getSizeInBytes(), data->triangles.ptr, false); sub->indexData->indexBuffer = ibuf; - sub->indexData->indexCount = numFaces; - sub->indexData->indexStart = 0; + + + } // Set material if one was given @@ -475,7 +576,7 @@ static void vectorMul(const Matrix &A, float *C) } -void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bounds) +void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bounds, Transformation original, std::vector boneSequence) { assert(shape != NULL); @@ -636,11 +737,29 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou std::list vertexBoneAssignments; + Nif::NiTriShapeCopy copy = shape->clone(); + if(!shape->controller.empty()) + { + Nif::Controller* cont = shape->controller.getPtr(); + if(cont->recType == RC_NiGeomMorpherController) + { + Nif::NiGeomMorpherController* morph = dynamic_cast (cont); + copy.morph = morph->data.get(); + copy.morph.setStartTime(morph->timeStart); + copy.morph.setStopTime(morph->timeStop); + } + + } //use niskindata for the position of vertices. if (!shape->skin.empty()) { - // vector that stores if the position if a vertex is absolute + + + + // vector that stores if the position of a vertex is absolute std::vector vertexPosAbsolut(numVerts,false); + std::vector vertexPosOriginal(numVerts, Ogre::Vector3::ZERO); + std::vector vertexNormalOriginal(numVerts, Ogre::Vector3::ZERO); float *ptrNormals = (float*)data->normals.ptr; //the bone from skin->bones[boneIndex] is linked to skin->data->bones[boneIndex] @@ -667,24 +786,50 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou break; } //get the bone from bones array of skindata + if(!mSkel->hasBone(shape->skin->bones[boneIndex].name.toString())) + std::cout << "We don't have this bone"; bonePtr = mSkel->getBone(shape->skin->bones[boneIndex].name.toString()); // final_vector = old_vector + old_rotation*new_vector*old_scale - vecPos = bonePtr->_getDerivedPosition() + + + + Nif::NiSkinData::BoneInfoCopy boneinfocopy; + boneinfocopy.trafo.rotation = convertRotation(it->trafo->rotation); + boneinfocopy.trafo.trans = convertVector3(it->trafo->trans); + boneinfocopy.bonename = shape->skin->bones[boneIndex].name.toString(); + boneinfocopy.bonehandle = bonePtr->getHandle(); + copy.boneinfo.push_back(boneinfocopy); + for (unsigned int i=0; iweights.length; i++) + { + vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * convertVector3(it->trafo->trans); vecRot = bonePtr->_getDerivedOrientation() * convertRotation(it->trafo->rotation); - - for (unsigned int i=0; iweights.length; i++) - { unsigned int verIndex = (it->weights.ptr + i)->vertex; + //boneinfo.weights.push_back(*(it->weights.ptr + i)); + Nif::NiSkinData::IndividualWeight ind; + ind.weight = (it->weights.ptr + i)->weight; + ind.boneinfocopyindex = copy.boneinfo.size() - 1; + if(copy.vertsToWeights.find(verIndex) == copy.vertsToWeights.end()) + { + std::vector blank; + blank.push_back(ind); + copy.vertsToWeights[verIndex] = blank; + } + else + { + copy.vertsToWeights[verIndex].push_back(ind); + } //Check if the vertex is relativ, FIXME: Is there a better solution? if (vertexPosAbsolut[verIndex] == false) { //apply transformation to the vertices Vector3 absVertPos = vecPos + vecRot * Vector3(ptr + verIndex *3); + absVertPos = absVertPos * (it->weights.ptr + i)->weight; + vertexPosOriginal[verIndex] = Vector3(ptr + verIndex *3); + mBoundingBox.merge(absVertPos); //convert it back to float * for (int j=0; j<3; j++) (ptr + verIndex*3)[j] = absVertPos[j]; @@ -694,6 +839,8 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou if (verIndex < data->normals.length) { Vector3 absNormalsPos = vecRot * Vector3(ptrNormals + verIndex *3); + absNormalsPos = absNormalsPos * (it->weights.ptr + i)->weight; + vertexNormalOriginal[verIndex] = Vector3(ptrNormals + verIndex *3); for (int j=0; j<3; j++) (ptrNormals + verIndex*3)[j] = absNormalsPos[j]; @@ -701,27 +848,67 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou vertexPosAbsolut[verIndex] = true; } + else + { + Vector3 absVertPos = vecPos + vecRot * vertexPosOriginal[verIndex]; + absVertPos = absVertPos * (it->weights.ptr + i)->weight; + Vector3 old = Vector3(ptr + verIndex *3); + absVertPos = absVertPos + old; + + mBoundingBox.merge(absVertPos); + //convert it back to float * + for (int j=0; j<3; j++) + (ptr + verIndex*3)[j] = absVertPos[j]; + + //apply rotation to the normals (not every vertex has a normal) + //FIXME: I guessed that vertex[i] = normal[i], is that true? + if (verIndex < data->normals.length) + { + Vector3 absNormalsPos = vecRot * vertexNormalOriginal[verIndex]; + absNormalsPos = absNormalsPos * (it->weights.ptr + i)->weight; + Vector3 oldNormal = Vector3(ptrNormals + verIndex *3); + absNormalsPos = absNormalsPos + oldNormal; + + for (int j=0; j<3; j++) + (ptrNormals + verIndex*3)[j] = absNormalsPos[j]; + } + } + VertexBoneAssignment vba; vba.boneIndex = bonePtr->getHandle(); vba.vertexIndex = verIndex; vba.weight = (it->weights.ptr + i)->weight; + vertexBoneAssignments.push_back(vba); } + boneIndex++; } + } else { + + copy.boneSequence = boneSequence; // Rotate, scale and translate all the vertices, const Matrix &rot = shape->trafo->rotation; const Vector &pos = shape->trafo->pos; float scale = shape->trafo->scale; + + copy.trafo.trans = convertVector3(original.pos); + copy.trafo.rotation = convertRotation(original.rotation); + copy.trafo.scale = original.scale; + //We don't use velocity for anything yet, so it does not need to be saved + + // Computes C = B + AxC*scale for (int i=0; igetBone(boneSequence[boneSequence.size() - 1]); + if(parentBone) + boneIndex = parentBone->getHandle(); + else + boneIndex = mSkel->getNumBones() - 1; + for(int i = 0; i < numVerts; i++){ + VertexBoneAssignment vba; + vba.boneIndex = boneIndex; + vba.vertexIndex = i; + vba.weight = 1; + vertexBoneAssignments.push_back(vba); + } + } } if (!hidden) { // Add this vertex set to the bounding box bounds.add(optr, numVerts); + shapes.push_back(copy); // Create the submesh createOgreSubMesh(shape, material, vertexBoneAssignments); } } -void NIFLoader::handleNode(Nif::Node *node, int flags, - const Transformation *trafo, BoundsFinder &bounds, Bone *parentBone) +void NIFLoader::calculateTransform() +{ + // Calculate transform + Matrix4 transform = Matrix4::IDENTITY; + transform = Matrix4::getScale(vector) * transform; + + // Check whether we have to flip vertex winding. + // We do have to, if we changed our right hand base. + // We can test it by using the cross product from X and Y and see, if it is a non-negative + // projection on Z. Actually it should be exactly Z, as we don't do non-uniform scaling yet, + // but the test is cheap either way. + Matrix3 m3; + transform.extract3x3Matrix(m3); + + if (m3.GetColumn(0).crossProduct(m3.GetColumn(1)).dotProduct(m3.GetColumn(2)) < 0) + { + mFlipVertexWinding = true; + } + + mTransform = transform; +} +void NIFLoader::handleNode(Nif::Node *node, int flags, + const Transformation *trafo, BoundsFinder &bounds, Ogre::Bone *parentBone, std::vector boneSequence) { - stack++; - //if( MWClass::isChest) - // cout << "u:" << node << "\n"; // Accumulate the flags from all the child nodes. This works for all // the flags we currently use, at least. flags |= node->flags; @@ -780,6 +1001,58 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, // the engine, just skip this entire node. return; } + + if (e->recType == RC_NiTextKeyExtraData){ + Nif::NiTextKeyExtraData* extra = dynamic_cast (e); + + std::ofstream file; + + if(mOutputAnimFiles){ + std::string cut = ""; + for(unsigned int i = 0; i < name.length(); i++) + { + if(!(name.at(i) == '\\' || name.at(i) == '/' || name.at(i) == '>' || name.at(i) == '<' || name.at(i) == '?' || name.at(i) == '*' || name.at(i) == '|' || name.at(i) == ':' || name.at(i) == '"')) + { + cut += name.at(i); + } + } + + std::cout << "Outputting " << cut << "\n"; + + file.open((verbosePath + "/Indices" + cut + ".txt").c_str()); + } + + for(std::vector::iterator textiter = extra->list.begin(); textiter != extra->list.end(); textiter++) + { + std::string text = textiter->text.toString(); + + replace(text.begin(), text.end(), '\n', '/'); + + text.erase(std::remove(text.begin(), text.end(), '\r'), text.end()); + std::size_t i = 0; + while(i < text.length()){ + while(i < text.length() && text.at(i) == '/' ){ + i++; + } + std::size_t first = i; + int length = 0; + while(i < text.length() && text.at(i) != '/' ){ + i++; + length++; + } + if(first < text.length()){ + //length = text.length() - first; + std::string sub = text.substr(first, length); + + if(mOutputAnimFiles) + file << "Time: " << textiter->time << "|" << sub << "\n"; + + textmappings[sub] = textiter->time; + } + } + } + file.close(); + } } Bone *bone = 0; @@ -790,20 +1063,15 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, //FIXME: "Bip01" isn't every time the root bone if (node->name == "Bip01" || node->name == "Root Bone") //root node, create a skeleton { - mSkel = SkeletonManager::getSingleton().create(getSkeletonName(), resourceGroup, true); - /*if (node->extra->recType == RC_NiTextKeyExtraData ) - { - //TODO: Get animation names - std::cout << node->name.toString() << " is root bone and has textkeyextradata!\n"; - }*/ + mSkel = SkeletonManager::getSingleton().create(getSkeletonName(), resourceGroup, true); } if (!mSkel.isNull()) //if there is a skeleton { std::string name = node->name.toString(); - //if (isBeast && isChest) - // std::cout << "NAME: " << name << "\n"; + boneSequence.push_back(name); + // Quick-n-dirty workaround for the fact that several // bones may have the same name. if(!mSkel->hasBone(name)) @@ -819,7 +1087,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, } } } - + Transformation original = *(node->trafo); // Apply the parent transformation to this node. We overwrite the // existing data with the final transformation. if (trafo) @@ -846,201 +1114,97 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, { NodeList &list = ((NiNode*)node)->children; int n = list.length(); - int i = 0; - if(isHands){ - //cout << "NumberOfNs: " << n << "Stack:" << stack << "\n"; - //if(stack == 3) - //n=0; - } - for (; itrafo, bounds, bone); + handleNode(&list[i], flags, node->trafo, bounds, bone, boneSequence); } } - else if (node->recType == RC_NiTriShape) + else if (node->recType == RC_NiTriShape && bNiTri) { - // For shapes - /*For Beast Skins, Shape Bone Names - Tri Left Foot - Tri Right Foot - Tri Tail - Tri Chest - */ - if((isChest && stack < 10 ) || (isHands && counter < 3) || !(isChest || isHands)){ //(isBeast && isChest && stack < 10 && counter == skincounter ) + std::string nodename = node->name.toString(); - std::string name = node->name.toString(); - //if (isChest) - //std::cout << "NAME: " << name << "\n"; - - if(isChest && isBeast && skincounter == 0 && name.compare("Tri Chest") == 0){ - //std::cout <<"BEASTCHEST1\n"; - handleNiTriShape(dynamic_cast(node), flags, bounds); - skincounter++; - } - else if(isChest && isBeast && skincounter == 1 && name.compare("Tri Tail") == 0){ - //std::cout <<"BEASTCHEST2\n"; - handleNiTriShape(dynamic_cast(node), flags, bounds); - skincounter++; - } - else if(isChest && isBeast && skincounter == 2 && name.compare("Tri Left Foot") == 0){ - //std::cout <<"BEASTCHEST3\n"; - handleNiTriShape(dynamic_cast(node), flags, bounds); - skincounter=1000; - } - else if (!isChest || !isBeast) + if (triname == "") { - handleNiTriShape(dynamic_cast(node), flags, bounds); + handleNiTriShape(dynamic_cast(node), flags, bounds, original, boneSequence); } - //if(isBeast && isChest) - //cout << "Handling Shape, Stack " << stack <<"\n"; - - - - counter++; - } - /*if(isHands){ - //cout << "Handling Shape, Stack " << stack <<"\n"; - counter++; - }*/ - + else if(nodename.length() >= triname.length()) + { + std::transform(nodename.begin(), nodename.end(), nodename.begin(), ::tolower); + if(triname == nodename.substr(0, triname.length())) + handleNiTriShape(dynamic_cast(node), flags, bounds, original, boneSequence); + } } - - stack--; } void NIFLoader::loadResource(Resource *resource) { - if(skincounter == 1000) - skincounter = 0; - stack = 0; - counter = 0; - std::string name = resource->getName(); - if(resourceName.compare(name) != 0) - { - skincounter = 0; - resourceName = name; - } - //std::cout <<"NAME:" << name; - //if(name.length() >= 20) - // {std::string split = name.substr(name.length() - 20, 20); - //if(name == - //std::cout <<"NAME:" << name << "LEN: " << name.length() << "\n"; - const std::string test ="meshes\\b\\B_N_Dark Elf_M_Skins.NIF"; - const std::string test2 ="meshes\\b\\B_N_Dark Elf_M_Skins.nif"; - const std::string test3 ="meshes\\b\\B_N_Redguard_F_Skins.NIF"; - const std::string test4 ="meshes\\b\\B_N_Redguard_F_Skins.nif"; - const std::string test5 ="meshes\\b\\B_N_Dark Elf_F_Skins.nif"; - const std::string test6 ="meshes\\b\\B_N_Redguard_M_Skins.nif"; - const std::string test7 ="meshes\\b\\B_N_Wood Elf_F_Skins.nif"; - const std::string test8 ="meshes\\b\\B_N_Wood Elf_M_Skins.nif"; - const std::string test9 ="meshes\\b\\B_N_Imperial_F_Skins.nif"; - const std::string test10 ="meshes\\b\\B_N_Imperial_M_Skins.nif"; - const std::string test11 ="meshes\\b\\B_N_Khajiit_F_Skins.nif"; - const std::string test12 ="meshes\\b\\B_N_Khajiit_M_Skins.nif"; - const std::string test13 ="meshes\\b\\B_N_Argonian_F_Skins.nif"; - const std::string test14 ="meshes\\b\\B_N_Argonian_M_Skins.nif"; - const std::string test15 ="meshes\\b\\B_N_Nord_F_Skins.nif"; - const std::string test16 ="meshes\\b\\B_N_Nord_M_Skins.nif"; - const std::string test17 ="meshes\\b\\B_N_Imperial_F_Skins.nif"; - const std::string test18 ="meshes\\b\\B_N_Imperial_M_Skins.nif"; - const std::string test19 ="meshes\\b\\B_N_Orc_F_Skins.nif"; - const std::string test20 ="meshes\\b\\B_N_Orc_M_Skins.nif"; - const std::string test21 ="meshes\\b\\B_N_Breton_F_Skins.nif"; - const std::string test22 ="meshes\\b\\B_N_Breton_M_Skins.nif"; - const std::string test23 ="meshes\\b\\B_N_High Elf_F_Skins.nif"; - const std::string test24 ="meshes\\b\\B_N_High Elf_M_Skins.nif"; - - //std::cout <<"LEN1:" << test.length() << "TEST: " << test << "\n"; - - - if(name.compare(test) == 0 || name.compare(test2) == 0 || name.compare(test3) == 0 || name.compare(test4) == 0 || - name.compare(test5) == 0 || name.compare(test6) == 0 || name.compare(test7) == 0 || name.compare(test8) == 0 || name.compare(test9) == 0 || - name.compare(test10) == 0 || name.compare(test11) == 0 || name.compare(test12) == 0 || name.compare(test13) == 0 || - name.compare(test14) == 0 || name.compare(test15) == 0 || name.compare(test16) == 0 || name.compare(test17) == 0 || - name.compare(test18) == 0 || name.compare(test19) == 0 || name.compare(test20) == 0 || name.compare(test21) == 0 || - name.compare(test22) == 0 || name.compare(test23) == 0 || name.compare(test24) == 0 - - ){ - //std::cout << "Welcome Chest\n"; - isChest = true; - if(name.compare(test11) == 0 || name.compare(test12) == 0 || name.compare(test13) == 0 || name.compare(test14) == 0) - { - isBeast = true; - //std::cout << "Welcome Beast\n"; - } - else - isBeast = false; - } - else - isChest = false; - const std::string hands ="meshes\\b\\B_N_Dark Elf_M_Hands.1st.NIF"; - const std::string hands2 ="meshes\\b\\B_N_Dark Elf_F_Hands.1st.NIF"; - const std::string hands3 ="meshes\\b\\B_N_Redguard_M_Hands.1st.nif"; - const std::string hands4 ="meshes\\b\\B_N_Redguard_F_Hands.1st.nif"; - const std::string hands5 ="meshes\\b\\b_n_argonian_m_hands.1st.nif"; - const std::string hands6 ="meshes\\b\\b_n_argonian_f_hands.1st.nif"; - const std::string hands7 ="meshes\\b\\B_N_Breton_M_Hand.1st.NIF"; - const std::string hands8 ="meshes\\b\\B_N_Breton_F_Hands.1st.nif"; - const std::string hands9 ="meshes\\b\\B_N_High Elf_M_Hands.1st.nif"; - const std::string hands10 ="meshes\\b\\B_N_High Elf_F_Hands.1st.nif"; - const std::string hands11 ="meshes\\b\\B_N_Nord_M_Hands.1st.nif"; - const std::string hands12 ="meshes\\b\\B_N_Nord_F_Hands.1st.nif"; - const std::string hands13 ="meshes\\b\\b_n_khajiit_m_hands.1st.nif"; - const std::string hands14 ="meshes\\b\\b_n_khajiit_f_hands.1st.nif"; - const std::string hands15 ="meshes\\b\\B_N_Orc_M_Hands.1st.nif"; - const std::string hands16 ="meshes\\b\\B_N_Orc_F_Hands.1st.nif"; - const std::string hands17 ="meshes\\b\\B_N_Wood Elf_M_Hands.1st.nif"; - const std::string hands18 ="meshes\\b\\B_N_Wood Elf_F_Hands.1st.nif"; - const std::string hands19 ="meshes\\b\\B_N_Imperial_M_Hands.1st.nif"; - const std::string hands20 ="meshes\\b\\B_N_Imperial_F_Hands.1st.nif"; - if(name.compare(hands) == 0 || name.compare(hands2) == 0 || name.compare(hands3) == 0 || name.compare(hands4) == 0 || - name.compare(hands5) == 0 || name.compare(hands6) == 0 || name.compare(hands7) == 0 || name.compare(hands8) == 0 || - name.compare(hands9) == 0 || name.compare(hands10) == 0 || name.compare(hands11) == 0 || name.compare(hands12) == 0 || - name.compare(hands13) == 0 || name.compare(hands14) == 0 || name.compare(hands15) == 0 || name.compare(hands16) == 0 || - name.compare(hands17) == 0 || name.compare(hands18) == 0 || name.compare(hands19) == 0 || name.compare(hands20) == 0) - { - //std::cout << "Welcome Hands1st\n"; - isHands = true; - isChest = false; - } - else - isHands = false; - - - /* - else if(name.compare(test3) == 0 || name.compare(test4) == 0) - { - std::cout << "\n\n\nWelcome FRedguard Chest\n\n\n"; - isChest = true; - } - else if(name.compare(test5) == 0 || name.compare(test6) == 0) - { - std::cout << "\n\n\nWelcome FRedguard Chest\n\n\n"; - isChest = true; - } - else if(name.compare(test7) == 0 || name.compare(test8) == 0) - { - std::cout << "\n\n\nWelcome FRedguard Chest\n\n\n"; - isChest = true; - } - else if(name.compare(test9) == 0 || name.compare(test10) == 0) - { - std::cout << "\n\n\nWelcome FRedguard Chest\n\n\n"; - isChest = true; - }*/ - - //if(split== "Skins.NIF") - // std::cout << "\nSPECIAL PROPS\n"; - resourceName = ""; - // Check if the resource already exists - //MeshPtr ptr = m->load(name, "custom"); - //cout << "THISNAME: " << ptr->getName() << "\n"; - //cout << "RESOURCE:"<< resource->getName(); + allanim.clear(); + shapes.clear(); + mBoundingBox.setNull(); mesh = 0; mSkel.setNull(); + flip = false; + name = resource->getName(); + char suffix = name.at(name.length() - 2); + bool addAnim = true; + bool hasAnim = false; + bool baddin = false; + bNiTri = true; + if(suffix == '*') + { + vector = Ogre::Vector3(-1,1,1); + flip = true; + } + else if(suffix == '?'){ + vector = Ogre::Vector3(1,-1,1); + flip = true; + } + else if(suffix == '<'){ + vector = Ogre::Vector3(1,1,-1); + flip = true; + } + else if(suffix == '>') + { + baddin = true; + bNiTri = true; + std::string sub = name.substr(name.length() - 6, 4); + + if(sub.compare("0000") != 0) + addAnim = false; + + } + + switch(name.at(name.length() - 1)) + { + case '"': + triname = "tri chest"; + break; + case '*': + triname = "tri tail"; + break; + case ':': + triname = "tri left foot"; + break; + case '<': + triname = "tri right foot"; + break; + case '>': + triname = "tri left hand"; + break; + case '?': + triname = "tri right hand"; + break; + default: + triname = ""; + break; + } + if(flip) + { + calculateTransform(); + } // Set up the VFS if it hasn't been done already if (!vfs) vfs = new OgreVFS(resourceGroup); @@ -1087,8 +1251,33 @@ void NIFLoader::loadResource(Resource *resource) } // Handle the node - handleNode(node, 0, NULL, bounds, 0); + std::vector boneSequence; + + + handleNode(node, 0, NULL, bounds, 0, boneSequence); + if(addAnim) + { + for(int i = 0; i < nif.numRecords(); i++) + { + Nif::NiKeyframeController *f = dynamic_cast(nif.getRecord(i)); + + if(f != NULL) + { + hasAnim = true; + Nif::Node *o = dynamic_cast(f->target.getPtr()); + Nif::NiKeyframeDataPtr data = f->data; + + if (f->timeStart == 10000000000000000) + continue; + data->setBonename(o->name.toString()); + data->setStartTime(f->timeStart); + data->setStopTime(f->timeStop); + + allanim.push_back(data.get()); + } + } + } // set the bounding value. if (bounds.isValid()) { @@ -1096,64 +1285,84 @@ void NIFLoader::loadResource(Resource *resource) bounds.maxX(), bounds.maxY(), bounds.maxZ())); mesh->_setBoundingSphereRadius(bounds.getRadius()); } + if(hasAnim && addAnim){ + allanimmap[name] = allanim; + alltextmappings[name] = textmappings; + } + if(!mSkel.isNull() && shapes.size() > 0 && addAnim) + { + allshapesmap[name] = shapes; - // set skeleton -// if (!skel.isNull()) -// mesh->setSkeletonName(getSkeletonName()); + } + + if(flip){ + mesh->_setBounds(mBoundingBox, false); + } + + if (!mSkel.isNull()) + { + mesh->_notifySkeleton(mSkel); + } } +void NIFLoader::addInMesh(Ogre::Mesh* input){ + addin.push_back(input); +} + + + 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); - MeshPtr resize; - - const std::string beast1 ="meshes\\b\\B_N_Khajiit_F_Skins.nif"; - const std::string beast2 ="meshes\\b\\B_N_Khajiit_M_Skins.nif"; - const std::string beast3 ="meshes\\b\\B_N_Argonian_F_Skins.nif"; - const std::string beast4 ="meshes\\b\\B_N_Argonian_M_Skins.nif"; - - const std::string beasttail1 ="tail\\b\\B_N_Khajiit_F_Skins.nif"; - const std::string beasttail2 ="tail\\b\\B_N_Khajiit_M_Skins.nif"; - const std::string beasttail3 ="tail\\b\\B_N_Argonian_F_Skins.nif"; - const std::string beasttail4 ="tail\\b\\B_N_Argonian_M_Skins.nif"; - + MeshPtr themesh; if (!ptr.isNull()){ - - //if(pieces > 1) - //cout << "It exists\n"; - resize = MeshPtr(ptr); - //resize->load(); - //resize->reload(); + themesh = MeshPtr(ptr); } else // Nope, create a new one. { - resize = MeshManager::getSingleton().createManual(name, group, NIFLoader::getSingletonPtr()); - //cout <<"EXISTING" << name << "\n"; - - //if(pieces > 1) - //cout << "Creating it\n"; - - - //resize->load(); - //resize->reload(); - //return 0; - ResourcePtr ptr = m->getByName(name, group); - resize = MeshPtr(ptr); - - //NIFLoader::getSingletonPtr()-> - /*ResourcePtr ptr = m->getByName(name, group); - if (!ptr.isNull()){ - if(pieces > 1) - cout << "It exists\n"; - resize = MeshPtr(ptr);*/ - //return resize; + themesh = MeshManager::getSingleton().createManual(name, group, NIFLoader::getSingletonPtr()); } - return resize; + return themesh; } +/* +This function shares much of the same code handleShapes() in MWRender::Animation +This function also creates new position and normal buffers for submeshes. +This function points to existing texture and IndexData buffers +*/ + +std::vector* NIFLoader::getAnim(std::string lowername){ + + std::map,ciLessBoost>::iterator iter = allanimmap.find(lowername); + std::vector* pass = 0; + if(iter != allanimmap.end()) + pass = &(iter->second); + return pass; + +} +std::vector* NIFLoader::getShapes(std::string lowername){ + + std::map,ciLessBoost>::iterator iter = allshapesmap.find(lowername); + std::vector* pass = 0; + if(iter != allshapesmap.end()) + pass = &(iter->second); + return pass; +} + +std::map* NIFLoader::getTextIndices(std::string lowername){ + std::map, ciLessBoost>::iterator iter = alltextmappings.find(lowername); + std::map* pass = 0; + if(iter != alltextmappings.end()) + pass = &(iter->second); + return pass; +} + + + /* More code currently not in use, from the old D source. This was used in the first attempt at loading NIF meshes, where each submesh diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index bf8a94266..62239bb4c 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -28,10 +28,38 @@ #include #include #include +#include +#include +#include +#include + +#include +#include "../nif/nif_file.hpp" +#include "../nif/node.hpp" +#include "../nif/data.hpp" +#include "../nif/property.hpp" +#include "../nif/controller.hpp" +#include "../nif/extra.hpp" +#include + +#include +#include +// For warning messages +#include +#include +using namespace boost::algorithm; class BoundsFinder; +struct ciLessBoost : std::binary_function +{ + bool operator() (const std::string & s1, const std::string & s2) const { + //case insensitive version of is_less + return lexicographical_compare(s1, s2, is_iless()); + } +}; + namespace Nif { class Node; @@ -52,6 +80,7 @@ namespace Mangle namespace NifOgre { + /** Manual resource loader for NIF meshes. This is the main class responsible for translating the internal NIF mesh structure into something Ogre can use. Later it will also handle the insertion of @@ -78,23 +107,34 @@ class NIFLoader : Ogre::ManualResourceLoader static Ogre::MeshPtr load(const std::string &name, const std::string &group="General"); - + //void insertMeshInsideBase(Ogre::Mesh* mesh); + std::vector* getAnim(std::string name); + std::vector* getShapes(std::string name); + std::map* getTextIndices(std::string name); + void addInMesh(Ogre::Mesh* input); Ogre::Vector3 convertVector3(const Nif::Vector& vec); Ogre::Quaternion convertRotation(const Nif::Matrix& rot); + void setOutputAnimFiles(bool output); + void setVerbosePath(std::string path); + private: - NIFLoader() : resourceGroup("General") { skincounter = 0; resourceName = "";} + NIFLoader() : resourceName(""), resourceGroup("General"), flip(false), mNormaliseNormals(false), + mFlipVertexWinding(false), mOutputAnimFiles(false) {} NIFLoader(NIFLoader& n) {} + void calculateTransform(); + + void warn(std::string msg); void fail(std::string msg); void handleNode( Nif::Node *node, int flags, - const Nif::Transformation *trafo, BoundsFinder &bounds, Ogre::Bone *parentBone); + const Nif::Transformation *trafo, BoundsFinder &bounds, Ogre::Bone *parentBone, std::vector boneSequence); - void handleNiTriShape(Nif::NiTriShape *shape, int flags, BoundsFinder &bounds); + void handleNiTriShape(Nif::NiTriShape *shape, int flags, BoundsFinder &bounds, Nif::Transformation original, std::vector boneSequence); void createOgreSubMesh(Nif::NiTriShape *shape, const Ogre::String &material, std::list &vertexBoneAssignments); @@ -124,21 +164,34 @@ class NIFLoader : Ogre::ManualResourceLoader // extension from .tga to .dds if the texture is missing. Mangle::VFS::OgreVFS *vfs; + std::string verbosePath; std::string resourceName; std::string resourceGroup; - int skincounter; - bool isChest; - bool isBeast; - bool isHands; - bool isFeet; - int counter; - int numbers; - int stack; + Ogre::Matrix4 mTransform; + Ogre::AxisAlignedBox mBoundingBox; + bool flip; + bool mNormaliseNormals; + bool mFlipVertexWinding; + bool bNiTri; + bool mOutputAnimFiles; std::multimap MaterialMap; // pointer to the ogre mesh which is currently build Ogre::Mesh *mesh; Ogre::SkeletonPtr mSkel; + Ogre::Vector3 vector; + std::vector shapes; + std::string name; + std::string triname; + std::vector allanim; + std::map textmappings; + std::map,ciLessBoost> alltextmappings; + std::map,ciLessBoost> allanimmap; + std::map,ciLessBoost> allshapesmap; + std::vector addin; + std::vector mAnim; + std::vector mS; + }; }