forked from mirror/openmw-tes3mp
Merge branch 'animation2'
This commit is contained in:
commit
0c2de2c00c
89 changed files with 3884 additions and 2535 deletions
|
@ -16,7 +16,7 @@ set(GAME_HEADER
|
||||||
source_group(game FILES ${GAME} ${GAME_HEADER})
|
source_group(game FILES ${GAME} ${GAME_HEADER})
|
||||||
|
|
||||||
add_openmw_dir (mwrender
|
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
|
add_openmw_dir (mwinput
|
||||||
|
@ -36,6 +36,7 @@ add_openmw_dir (mwscript
|
||||||
locals scriptmanager compilercontext interpretercontext cellextensions miscextensions
|
locals scriptmanager compilercontext interpretercontext cellextensions miscextensions
|
||||||
guiextensions soundextensions skyextensions statsextensions containerextensions
|
guiextensions soundextensions skyextensions statsextensions containerextensions
|
||||||
aiextensions controlextensions extensions globalscripts ref dialogueextensions
|
aiextensions controlextensions extensions globalscripts ref dialogueextensions
|
||||||
|
animationextensions
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwsound
|
add_openmw_dir (mwsound
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <components/esm/esm_reader.hpp>
|
#include <components/esm/esm_reader.hpp>
|
||||||
#include <components/files/path.hpp>
|
#include <components/files/path.hpp>
|
||||||
#include <components/nifbullet/bullet_nif_loader.hpp>
|
#include <components/nifbullet/bullet_nif_loader.hpp>
|
||||||
|
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||||
|
|
||||||
#include "mwinput/inputmanager.hpp"
|
#include "mwinput/inputmanager.hpp"
|
||||||
|
|
||||||
|
@ -46,6 +47,7 @@
|
||||||
|
|
||||||
#include "mwmechanics/mechanicsmanager.hpp"
|
#include "mwmechanics/mechanicsmanager.hpp"
|
||||||
|
|
||||||
|
|
||||||
void OMW::Engine::executeLocalScripts()
|
void OMW::Engine::executeLocalScripts()
|
||||||
{
|
{
|
||||||
MWWorld::LocalScripts& localScripts = mEnvironment.mWorld->getLocalScripts();
|
MWWorld::LocalScripts& localScripts = mEnvironment.mWorld->getLocalScripts();
|
||||||
|
@ -69,6 +71,7 @@ void OMW::Engine::executeLocalScripts()
|
||||||
|
|
||||||
void OMW::Engine::updateFocusReport (float duration)
|
void OMW::Engine::updateFocusReport (float duration)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ((mFocusTDiff += duration)>0.25)
|
if ((mFocusTDiff += duration)>0.25)
|
||||||
{
|
{
|
||||||
mFocusTDiff = 0;
|
mFocusTDiff = 0;
|
||||||
|
@ -81,8 +84,10 @@ void OMW::Engine::updateFocusReport (float duration)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle);
|
MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle);
|
||||||
|
|
||||||
if (!ptr.isEmpty())
|
if (!ptr.isEmpty()){
|
||||||
name = MWWorld::Class::get (ptr).getName (ptr);
|
name = MWWorld::Class::get (ptr).getName (ptr);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name!=mFocusName)
|
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)
|
bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -135,6 +147,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||||
mEnvironment.mWorld->advanceTime (
|
mEnvironment.mWorld->advanceTime (
|
||||||
mEnvironment.mFrameDuration*mEnvironment.mWorld->getTimeScaleFactor()/3600);
|
mEnvironment.mFrameDuration*mEnvironment.mWorld->getTimeScaleFactor()/3600);
|
||||||
|
|
||||||
|
|
||||||
if (changed) // keep change flag for another frame, if cell changed happend in local script
|
if (changed) // keep change flag for another frame, if cell changed happend in local script
|
||||||
mEnvironment.mWorld->markCellAsUnchanged();
|
mEnvironment.mWorld->markCellAsUnchanged();
|
||||||
|
|
||||||
|
@ -287,6 +300,7 @@ void OMW::Engine::setReportFocus (bool report)
|
||||||
|
|
||||||
void OMW::Engine::go()
|
void OMW::Engine::go()
|
||||||
{
|
{
|
||||||
|
mFocusTDiff = 0;
|
||||||
assert (!mEnvironment.mWorld);
|
assert (!mEnvironment.mWorld);
|
||||||
assert (!mCellName.empty());
|
assert (!mCellName.empty());
|
||||||
assert (!mMaster.empty());
|
assert (!mMaster.empty());
|
||||||
|
@ -330,6 +344,7 @@ void OMW::Engine::go()
|
||||||
mGuiManager = new OEngine::GUI::MyGUIManager(mOgre->getWindow(), mOgre->getScene(), false,
|
mGuiManager = new OEngine::GUI::MyGUIManager(mOgre->getWindow(), mOgre->getScene(), false,
|
||||||
mCfgMgr.getLogPath().string() + std::string("/"));
|
mCfgMgr.getLogPath().string() + std::string("/"));
|
||||||
|
|
||||||
|
|
||||||
// Create window manager - this manages all the MW-specific GUI windows
|
// Create window manager - this manages all the MW-specific GUI windows
|
||||||
MWScript::registerExtensions (mExtensions);
|
MWScript::registerExtensions (mExtensions);
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,8 @@ namespace OMW
|
||||||
/// Font encoding
|
/// Font encoding
|
||||||
void setEncoding(const std::string& encoding);
|
void setEncoding(const std::string& encoding);
|
||||||
|
|
||||||
|
void setAnimationVerbose(bool animverbose);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Cfg::ConfigurationManager& mCfgMgr;
|
Cfg::ConfigurationManager& mCfgMgr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -78,6 +78,9 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Cfg::Configuratio
|
||||||
("fps", boost::program_options::value<int>()->implicit_value(1)
|
("fps", boost::program_options::value<int>()->implicit_value(1)
|
||||||
->default_value(0), "fps counter detail (0 = off, 1 = fps counter, 2 = full detail)")
|
->default_value(0), "fps counter detail (0 = off, 1 = fps counter, 2 = full detail)")
|
||||||
|
|
||||||
|
("anim-verbose", boost::program_options::value<bool>()->implicit_value(true)
|
||||||
|
->default_value(false), "output animation indices files")
|
||||||
|
|
||||||
("debug", boost::program_options::value<bool>()->implicit_value(true)
|
("debug", boost::program_options::value<bool>()->implicit_value(true)
|
||||||
->default_value(false), "debug mode")
|
->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<bool>());
|
engine.setScriptsVerbosity(variables["script-verbose"].as<bool>());
|
||||||
engine.setCompileAll(variables["script-all"].as<bool>());
|
engine.setCompileAll(variables["script-all"].as<bool>());
|
||||||
engine.setReportFocus(variables["report-focus"].as<bool>());
|
engine.setReportFocus(variables["report-focus"].as<bool>());
|
||||||
|
engine.setAnimationVerbose(variables["anim-verbose"].as<bool>());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
#include "activator.hpp"
|
#include "activator.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
#include <components/esm/loadacti.hpp>
|
#include <components/esm/loadacti.hpp>
|
||||||
|
|
||||||
|
@ -7,27 +8,39 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Activator::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Activator>();
|
ptr.get<ESM::Activator>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertObjectPhysics();
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Activator::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Activator>();
|
||||||
|
|
||||||
|
|
||||||
|
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
|
std::string Activator::getName (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData> *ref =
|
||||||
|
|
|
@ -9,10 +9,11 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
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);
|
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
|
@ -8,29 +8,41 @@
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
#include "containerutil.hpp"
|
#include "containerutil.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Apparatus::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Apparatus::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Apparatus>();
|
ptr.get<ESM::Apparatus>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertObjectPhysics();
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Apparatus::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Apparatus>();
|
||||||
|
|
||||||
|
|
||||||
|
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
|
std::string Apparatus::getName (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWCLASS_APPARATUS_H
|
#define GAME_MWCLASS_APPARATUS_H
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -9,10 +10,11 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
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);
|
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
|
@ -8,29 +8,40 @@
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
#include "containerutil.hpp"
|
#include "containerutil.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Armor::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Armor::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Armor>();
|
ptr.get<ESM::Armor>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertObjectPhysics();
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Armor::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Armor>();
|
||||||
|
|
||||||
|
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
|
std::string Armor::getName (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWCLASS_ARMOR_H
|
#define GAME_MWCLASS_ARMOR_H
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -9,10 +10,11 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
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);
|
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
|
@ -8,29 +8,41 @@
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
#include "containerutil.hpp"
|
#include "containerutil.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Book::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Book::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Book>();
|
ptr.get<ESM::Book>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertObjectPhysics();
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Book::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Book>();
|
||||||
|
|
||||||
|
|
||||||
|
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
|
std::string Book::getName (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWCLASS_BOOK_H
|
#define GAME_MWCLASS_BOOK_H
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -9,10 +10,11 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
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);
|
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
|
@ -8,29 +8,41 @@
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
#include "containerutil.hpp"
|
#include "containerutil.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Clothing::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Clothing::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Clothing>();
|
ptr.get<ESM::Clothing>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertObjectPhysics();
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Clothing::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Clothing>();
|
||||||
|
|
||||||
|
|
||||||
|
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
|
std::string Clothing::getName (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWCLASS_CLOTHING_H
|
#define GAME_MWCLASS_CLOTHING_H
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -9,10 +10,11 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
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);
|
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
|
@ -7,27 +7,38 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Container::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Container::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Container>();
|
ptr.get<ESM::Container>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertObjectPhysics();
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Container::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Container>();
|
||||||
|
|
||||||
|
|
||||||
|
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
|
std::string Container::getName (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref =
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWCLASS_CONTAINER_H
|
#define GAME_MWCLASS_CONTAINER_H
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -9,10 +10,11 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
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);
|
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include "../mwworld/actiontalk.hpp"
|
#include "../mwworld/actiontalk.hpp"
|
||||||
#include "../mwworld/environment.hpp"
|
#include "../mwworld/environment.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
#include "../mwmechanics/mechanicsmanager.hpp"
|
#include "../mwmechanics/mechanicsmanager.hpp"
|
||||||
|
|
||||||
|
@ -23,21 +22,34 @@ namespace MWClass
|
||||||
return ref->base->mId;
|
return ref->base->mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Creature::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =
|
|
||||||
|
/*ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Creature>();
|
ptr.get<ESM::Creature>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{*/
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Actors& actors = renderingInterface.getActors();
|
||||||
cellRender.insertMesh("meshes\\" + model);
|
actors.insertCreature(ptr);
|
||||||
cellRender.insertActorPhysics();
|
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Creature::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Creature>();
|
||||||
|
|
||||||
|
|
||||||
|
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
|
void Creature::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
#define GAME_MWCLASS_CREATURE_H
|
#define GAME_MWCLASS_CREATURE_H
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwrender/renderinginterface.hpp"
|
||||||
|
#include "../mwrender/actors.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -12,10 +15,11 @@ namespace MWClass
|
||||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||||
///< Return ID of \a ptr
|
///< Return ID of \a ptr
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
|
||||||
///< Enable reference; only does the non-rendering part
|
///< Enable reference; only does the non-rendering part
|
||||||
|
|
||||||
|
|
|
@ -12,29 +12,42 @@
|
||||||
#include "../mwworld/environment.hpp"
|
#include "../mwworld/environment.hpp"
|
||||||
#include "../mwworld/world.hpp"
|
#include "../mwworld/world.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Door::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Door::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Door>();
|
ptr.get<ESM::Door>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertObjectPhysics();
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Door::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Door>();
|
||||||
|
|
||||||
|
|
||||||
|
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
|
std::string Door::getName (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWCLASS_DOOR_H
|
#define GAME_MWCLASS_DOOR_H
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -9,10 +10,11 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
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);
|
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
|
@ -8,29 +8,42 @@
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
#include "containerutil.hpp"
|
#include "containerutil.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Ingredient::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Ingredient::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Ingredient>();
|
ptr.get<ESM::Ingredient>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertObjectPhysics();
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Ingredient::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Ingredient>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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
|
std::string Ingredient::getName (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWCLASS_INGREDIENT_H
|
#define GAME_MWCLASS_INGREDIENT_H
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -9,10 +10,11 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
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);
|
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
|
@ -10,41 +10,48 @@
|
||||||
#include "../mwworld/nullaction.hpp"
|
#include "../mwworld/nullaction.hpp"
|
||||||
#include "../mwworld/environment.hpp"
|
#include "../mwworld/environment.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
#include "../mwsound/soundmanager.hpp"
|
#include "../mwsound/soundmanager.hpp"
|
||||||
|
|
||||||
#include "containerutil.hpp"
|
#include "containerutil.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Light::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Light::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Light>();
|
ptr.get<ESM::Light>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
cellRender.insertObjectPhysics();
|
|
||||||
|
|
||||||
// Extract the color and convert to floating point
|
|
||||||
const int color = ref->base->data.color;
|
const int color = ref->base->data.color;
|
||||||
const float r = ((color >> 0) & 0xFF) / 255.0f;
|
const float r = ((color >> 0) & 0xFF) / 255.0f;
|
||||||
const float g = ((color >> 8) & 0xFF) / 255.0f;
|
const float g = ((color >> 8) & 0xFF) / 255.0f;
|
||||||
const float b = ((color >> 16) & 0xFF) / 255.0f;
|
const float b = ((color >> 16) & 0xFF) / 255.0f;
|
||||||
const float radius = float (ref->base->data.radius);
|
const float radius = float (ref->base->data.radius);
|
||||||
cellRender.insertLight (r, g, b, radius);
|
objects.insertLight (ptr, r, g, b, radius);
|
||||||
|
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Light::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Light>();
|
||||||
|
|
||||||
|
|
||||||
|
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
|
void Light::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWCLASS_LIGHT_H
|
#define GAME_MWCLASS_LIGHT_H
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -9,10 +10,11 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
|
||||||
///< Enable reference; only does the non-rendering part
|
///< Enable reference; only does the non-rendering part
|
||||||
/// \attention This is not the same as the script instruction with the same name. References
|
/// \attention This is not the same as the script instruction with the same name. References
|
||||||
|
|
|
@ -8,29 +8,41 @@
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
#include "containerutil.hpp"
|
#include "containerutil.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Lockpick::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Lockpick::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Tool>();
|
ptr.get<ESM::Tool>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertObjectPhysics();
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Lockpick::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Tool>();
|
||||||
|
|
||||||
|
|
||||||
|
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
|
std::string Lockpick::getName (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWCLASS_LOCKPICK_H
|
#define GAME_MWCLASS_LOCKPICK_H
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -9,10 +10,11 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
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);
|
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
|
@ -8,29 +8,40 @@
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
#include "containerutil.hpp"
|
#include "containerutil.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Miscellaneous::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Miscellaneous>();
|
ptr.get<ESM::Miscellaneous>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertObjectPhysics();
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Miscellaneous::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Miscellaneous>();
|
||||||
|
|
||||||
|
|
||||||
|
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
|
std::string Miscellaneous::getName (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWCLASS_MISC_H
|
#define GAME_MWCLASS_MISC_H
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -9,10 +10,11 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
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);
|
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
#include "../mwworld/environment.hpp"
|
#include "../mwworld/environment.hpp"
|
||||||
#include "../mwworld/world.hpp"
|
#include "../mwworld/world.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
#include "../mwmechanics/mechanicsmanager.hpp"
|
#include "../mwmechanics/mechanicsmanager.hpp"
|
||||||
#include <OgreSceneNode.h>
|
#include <OgreSceneNode.h>
|
||||||
|
|
||||||
|
@ -32,229 +30,31 @@ namespace MWClass
|
||||||
return ref->base->mId;
|
return ref->base->mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Npc::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
//Ogre::SceneNode *chest;
|
renderingInterface.getActors().insertNPC(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::NPC>();
|
ptr.get<ESM::NPC>();
|
||||||
|
|
||||||
//Store scenenodes by npc's name + bodypart [0] , npc's name + bodypart [1]
|
|
||||||
//Ex. Fargothchest , Fargothneck
|
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
|
|
||||||
std::string hairID = ref->base->hair;
|
|
||||||
std::string headID = ref->base->head;
|
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 bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4);
|
||||||
std::string headModel = "meshes\\" +
|
bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_";
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
//TODO: define consts for each bodypart e.g. chest, foot, wrist... and put the parts in the
|
std::string smodel = "meshes\\base_anim.nif";
|
||||||
// right place
|
if(beast)
|
||||||
const ESM::BodyPart *bodyPart =
|
smodel = "meshes\\base_animkna.nif";
|
||||||
environment.mWorld->getStore().bodyParts.search (bodyRaceID + "chest");
|
physics.insertActorPhysics(ptr, smodel);
|
||||||
|
|
||||||
//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";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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
|
void Npc::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
class Npc : public MWWorld::Class
|
class Npc : public MWWorld::Class
|
||||||
|
@ -12,10 +13,11 @@ namespace MWClass
|
||||||
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
virtual std::string getId (const MWWorld::Ptr& ptr) const;
|
||||||
///< Return ID of \a ptr
|
///< Return ID of \a ptr
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
|
||||||
///< Enable reference; only does the non-rendering part
|
///< Enable reference; only does the non-rendering part
|
||||||
|
|
||||||
|
|
|
@ -8,29 +8,41 @@
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
#include "containerutil.hpp"
|
#include "containerutil.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Potion::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Potion>();
|
ptr.get<ESM::Potion>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertObjectPhysics();
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Potion::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Potion>();
|
||||||
|
|
||||||
|
|
||||||
|
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
|
std::string Potion::getName (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWCLASS_POTION_H
|
#define GAME_MWCLASS_POTION_H
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -9,10 +10,11 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
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);
|
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
|
@ -8,29 +8,42 @@
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
#include "containerutil.hpp"
|
#include "containerutil.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Probe::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Probe::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Probe>();
|
ptr.get<ESM::Probe>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertObjectPhysics();
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Probe::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Probe>();
|
||||||
|
|
||||||
|
|
||||||
|
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
|
std::string Probe::getName (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =
|
||||||
|
@ -38,7 +51,6 @@ namespace MWClass
|
||||||
|
|
||||||
return ref->base->name;
|
return ref->base->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<MWWorld::Action> Probe::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Probe::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,16 +3,18 @@
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
class Probe : public MWWorld::Class
|
class Probe : public MWWorld::Class
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
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);
|
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
|
@ -8,29 +8,40 @@
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
#include "containerutil.hpp"
|
#include "containerutil.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Repair::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Repair::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Repair>();
|
ptr.get<ESM::Repair>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertObjectPhysics();
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Repair::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Repair>();
|
||||||
|
|
||||||
|
|
||||||
|
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
|
std::string Repair::getName (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref =
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWCLASS_REPAIR_H
|
#define GAME_MWCLASS_REPAIR_H
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -9,10 +10,11 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
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);
|
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
|
@ -5,27 +5,39 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Static::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Static::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Static, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Static, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Static>();
|
ptr.get<ESM::Static>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData, true);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertObjectPhysics();
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Static::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Static, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Static>();
|
||||||
|
|
||||||
|
|
||||||
|
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
|
std::string Static::getName (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWCLASS_STATIC_H
|
#define GAME_MWCLASS_STATIC_H
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -9,10 +10,11 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
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);
|
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
|
@ -8,29 +8,41 @@
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
|
||||||
#include "../mwrender/cellimp.hpp"
|
|
||||||
|
|
||||||
#include "containerutil.hpp"
|
#include "containerutil.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
void Weapon::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Weapon::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
|
||||||
ptr.get<ESM::Weapon>();
|
ptr.get<ESM::Weapon>();
|
||||||
|
|
||||||
assert (ref->base != NULL);
|
assert (ref->base != NULL);
|
||||||
const std::string &model = ref->base->model;
|
const std::string &model = ref->base->model;
|
||||||
|
|
||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
|
MWRender::Objects& objects = renderingInterface.getObjects();
|
||||||
cellRender.insertMesh ("meshes\\" + model);
|
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
|
||||||
cellRender.insertObjectPhysics();
|
objects.insertMesh(ptr, "meshes\\" + model);
|
||||||
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Weapon::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Weapon>();
|
||||||
|
|
||||||
|
|
||||||
|
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
|
std::string Weapon::getName (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
|
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWCLASS_WEAPON_H
|
#define GAME_MWCLASS_WEAPON_H
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwrender/objects.hpp"
|
||||||
|
|
||||||
namespace MWClass
|
namespace MWClass
|
||||||
{
|
{
|
||||||
|
@ -9,10 +10,11 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||||
MWWorld::Environment& environment) const;
|
|
||||||
///< Add reference into a cell for rendering
|
///< 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;
|
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);
|
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||||
/// can return an empty string.
|
/// can return an empty string.
|
||||||
|
|
|
@ -250,6 +250,7 @@ namespace MWMechanics
|
||||||
while (iter!=mActors.end())
|
while (iter!=mActors.end())
|
||||||
if (iter->getCell()==cellStore)
|
if (iter->getCell()==cellStore)
|
||||||
{
|
{
|
||||||
|
//std::cout << "Erasing an actor";
|
||||||
mActors.erase (iter++);
|
mActors.erase (iter++);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
130
apps/openmw/mwrender/actors.cpp
Normal file
130
apps/openmw/mwrender/actors.cpp
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
#include "actors.hpp"
|
||||||
|
#include <OgreSceneNode.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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<MWWorld::Ptr, Animation*>(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<MWWorld::Ptr::CellStore *, Ogre::SceneNode *>::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<MWWorld::Ptr, Animation*>::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<MWWorld::Ptr, Animation*>::iterator iter = mAllActors.begin(); iter != mAllActors.end(); iter++)
|
||||||
|
{
|
||||||
|
(iter->second)->runAnimation(mEnvironment.mFrameDuration);
|
||||||
|
}
|
||||||
|
}
|
59
apps/openmw/mwrender/actors.hpp
Normal file
59
apps/openmw/mwrender/actors.hpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#ifndef _GAME_RENDER_ACTORS_H
|
||||||
|
#define _GAME_RENDER_ACTORS_H
|
||||||
|
|
||||||
|
#include "components/esm_store/cell_store.hpp"
|
||||||
|
#include <map>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <openengine/ogre/renderer.hpp>
|
||||||
|
#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 <openengine/bullet/physic.hpp>
|
||||||
|
|
||||||
|
namespace MWRender{
|
||||||
|
class Actors{
|
||||||
|
OEngine::Render::OgreRenderer &mRend;
|
||||||
|
std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes;
|
||||||
|
Ogre::SceneNode* mMwRoot;
|
||||||
|
MWWorld::Environment& mEnvironment;
|
||||||
|
std::map<MWWorld::Ptr, Animation*> 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
|
568
apps/openmw/mwrender/animation.cpp
Normal file
568
apps/openmw/mwrender/animation.cpp
Normal file
|
@ -0,0 +1,568 @@
|
||||||
|
#include "animation.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace MWRender{
|
||||||
|
std::map<std::string, int> 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<std::string, float>::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<std::string, float>::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<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel){
|
||||||
|
bool useHandles = skel == creaturemodel->getSkeleton();
|
||||||
|
shapeNumber = 0;
|
||||||
|
|
||||||
|
std::vector<Nif::NiTriShapeCopy>::iterator allshapesiter;
|
||||||
|
for(allshapesiter = allshapes->begin(); allshapesiter != allshapes->end(); allshapesiter++)
|
||||||
|
|
||||||
|
{
|
||||||
|
//std::map<unsigned short, PosAndRot> vecPosRot;
|
||||||
|
|
||||||
|
Nif::NiTriShapeCopy& copy = *allshapesiter;
|
||||||
|
std::vector<Ogre::Vector3>* allvertices = ©.vertices;
|
||||||
|
|
||||||
|
//std::set<unsigned int> vertices;
|
||||||
|
//std::set<unsigned int> normals;
|
||||||
|
//std::vector<Nif::NiSkinData::BoneInfoCopy> boneinfovector = copy.boneinfo;
|
||||||
|
std::map<int, std::vector<Nif::NiSkinData::IndividualWeight> >* 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<Ogre::Real*>(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
|
||||||
|
//Ogre::HardwareVertexBufferSharedPtr vbufNormal = creaturemodel->getMesh()->getSubMesh(copy.sname)->vertexData->vertexBufferBinding->getBuffer(1);
|
||||||
|
// Ogre::Real* pRealNormal = static_cast<Ogre::Real*>(vbufNormal->lock(Ogre::HardwareBuffer::HBL_NORMAL));
|
||||||
|
|
||||||
|
std::vector<Ogre::Vector3> 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<std::size_t> (shapeNumber))
|
||||||
|
{
|
||||||
|
std::vector<int> 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<Ogre::Vector3> 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<int, std::vector<Nif::NiSkinData::IndividualWeight> >::iterator iter = verticesToChange->begin();
|
||||||
|
iter != verticesToChange->end(); iter++)
|
||||||
|
{
|
||||||
|
std::vector<Nif::NiSkinData::IndividualWeight> 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<std::string> boneSequence = copy.boneSequence;
|
||||||
|
std::vector<std::string>::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<float> 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<Nif::NiKeyframeData>::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<Ogre::Quaternion> quats = iter->getQuat();
|
||||||
|
|
||||||
|
std::vector<float> ttime = iter->gettTime();
|
||||||
|
std::vector<float>::iterator ttimeiter = ttime.begin();
|
||||||
|
|
||||||
|
std::vector<float> rtime = iter->getrTime();
|
||||||
|
int rindexJ = 0;
|
||||||
|
timeIndex(time, rtime, rindexI[slot], rindexJ, x2);
|
||||||
|
int tindexJ = 0;
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<Ogre::Vector3> 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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
71
apps/openmw/mwrender/animation.hpp
Normal file
71
apps/openmw/mwrender/animation.hpp
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#ifndef _GAME_RENDER_ANIMATION_H
|
||||||
|
#define _GAME_RENDER_ANIMATION_H
|
||||||
|
#include <components/nif/data.hpp>
|
||||||
|
#include <openengine/ogre/renderer.hpp>
|
||||||
|
#include "../mwworld/refdata.hpp"
|
||||||
|
#include "../mwworld/ptr.hpp"
|
||||||
|
#include "../mwworld/actiontalk.hpp"
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
|
#include <components/nif/node.hpp>
|
||||||
|
#include <map>
|
||||||
|
#include <openengine/bullet/physic.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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<std::string, int> mUniqueIDs;
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::vector<Nif::NiTriShapeCopy>* > 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::vector<int>rindexI;
|
||||||
|
//Represents a translation index for each bone
|
||||||
|
std::vector<int>tindexI;
|
||||||
|
|
||||||
|
//Only shapes with morphing data will use a shape number
|
||||||
|
int shapeNumber;
|
||||||
|
std::vector<std::vector<int> > shapeIndexI;
|
||||||
|
|
||||||
|
//Ogre::SkeletonInstance* skel;
|
||||||
|
std::vector<Nif::NiTriShapeCopy>* shapes; //All the NiTriShapeData for a creature
|
||||||
|
std::vector<Ogre::Entity*> entityparts;
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<Nif::NiKeyframeData>* transformations;
|
||||||
|
std::map<std::string,float>* textmappings;
|
||||||
|
Ogre::Entity* base;
|
||||||
|
void handleShapes(std::vector<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel);
|
||||||
|
void handleAnimationTransforms();
|
||||||
|
bool timeIndex( float time, std::vector<float> 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
|
|
@ -1,67 +0,0 @@
|
||||||
#include "cellimp.hpp"
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <iostream>
|
|
||||||
#include <exception>
|
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
|
||||||
#include "../mwworld/ptr.hpp"
|
|
||||||
|
|
||||||
using namespace MWRender;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void insertCellRefList (CellRenderImp& cellRender, MWWorld::Environment& environment,
|
|
||||||
T& cellRefList, ESMS::CellStore<MWWorld::RefData> &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<MWWorld::RefData> &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);
|
|
||||||
}
|
|
|
@ -1,95 +0,0 @@
|
||||||
#ifndef _GAME_RENDER_CELLIMP_H
|
|
||||||
#define _GAME_RENDER_CELLIMP_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "components/esm_store/cell_store.hpp"
|
|
||||||
|
|
||||||
#include "../mwworld/refdata.hpp"
|
|
||||||
#include <OgreMath.h>
|
|
||||||
|
|
||||||
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<MWWorld::RefData> &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
|
|
62
apps/openmw/mwrender/creatureanimation.cpp
Normal file
62
apps/openmw/mwrender/creatureanimation.cpp
Normal file
|
@ -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<ESM::Creature, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Creature>();
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
apps/openmw/mwrender/creatureanimation.hpp
Normal file
26
apps/openmw/mwrender/creatureanimation.hpp
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef _GAME_RENDER_CREATUREANIMATION_H
|
||||||
|
#define _GAME_RENDER_CREATUREANIMATION_H
|
||||||
|
|
||||||
|
#include "animation.hpp"
|
||||||
|
#include <components/nif/node.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#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
|
38
apps/openmw/mwrender/debugging.cpp
Normal file
38
apps/openmw/mwrender/debugging.cpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#include "debugging.hpp"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#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 <components/esm/loadstat.hpp>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
43
apps/openmw/mwrender/debugging.hpp
Normal file
43
apps/openmw/mwrender/debugging.hpp
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef _GAME_RENDER_MWSCENE_H
|
||||||
|
#define _GAME_RENDER_MWSCENE_H
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <openengine/ogre/renderer.hpp>
|
||||||
|
#include <openengine/bullet/physic.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
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
|
|
@ -1,454 +0,0 @@
|
||||||
#include "exterior.hpp"
|
|
||||||
|
|
||||||
#include <OgreEntity.h>
|
|
||||||
#include <OgreLight.h>
|
|
||||||
#include <OgreSceneNode.h>
|
|
||||||
#include <OgreCamera.h>
|
|
||||||
#include <OgreSceneManager.h>
|
|
||||||
|
|
||||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
|
||||||
#include "mwscene.hpp"
|
|
||||||
#include <libs/mangle/vfs/servers/ogre_vfs.hpp>
|
|
||||||
#include "mwscene.hpp"
|
|
||||||
#include <Ogre.h>
|
|
||||||
|
|
||||||
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<MWWorld::RefData> &_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<Ogre::SceneNode*> (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<Ogre::SceneNode*> (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<Ogre::SceneNode*> (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<Ogre::SceneNode*> (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<MovableObject*>(itObject.getNext());
|
|
||||||
i_pSceneNode->getCreator()->destroyMovableObject( pObject );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recurse to child SceneNodes
|
|
||||||
SceneNode::ChildNodeIterator itChild = i_pSceneNode->getChildIterator();
|
|
||||||
|
|
||||||
while ( itChild.hasMoreElements() )
|
|
||||||
{
|
|
||||||
SceneNode* pChildNode = static_cast<SceneNode*>(itChild.getNext());
|
|
||||||
destroyAllAttachedMovableObjects( pChildNode );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 <OgreMath.h>
|
|
||||||
#include <Ogre.h>
|
|
||||||
|
|
||||||
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<MWWorld::RefData> &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<MWWorld::RefData> &_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
|
|
|
@ -1,409 +0,0 @@
|
||||||
#include "interior.hpp"
|
|
||||||
|
|
||||||
#include <OgreEntity.h>
|
|
||||||
#include <OgreLight.h>
|
|
||||||
#include <OgreSceneNode.h>
|
|
||||||
#include <OgreCamera.h>
|
|
||||||
#include <OgreSceneManager.h>
|
|
||||||
#include <OgreMath.h>
|
|
||||||
|
|
||||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
|
||||||
#include "mwscene.hpp"
|
|
||||||
#include <Ogre.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <libs/mangle/vfs/servers/ogre_vfs.hpp>
|
|
||||||
|
|
||||||
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<Ogre::SceneNode*> (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<Ogre::SceneNode*> (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<Ogre::SceneNode*> (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<MovableObject*>(itObject.getNext());
|
|
||||||
i_pSceneNode->getCreator()->destroyMovableObject( pObject );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recurse to child SceneNodes
|
|
||||||
SceneNode::ChildNodeIterator itChild = i_pSceneNode->getChildIterator();
|
|
||||||
|
|
||||||
while ( itChild.hasMoreElements() )
|
|
||||||
{
|
|
||||||
SceneNode* pChildNode = static_cast<SceneNode*>(itChild.getNext());
|
|
||||||
DestroyAllAttachedMovableObjects( pChildNode );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
|
@ -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 <OgreSceneNode.h>
|
|
||||||
|
|
||||||
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<MWWorld::RefData> &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<MWWorld::RefData> &_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
|
|
|
@ -1,89 +0,0 @@
|
||||||
#include "mwscene.hpp"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#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 <components/esm/loadstat.hpp>
|
|
||||||
|
|
||||||
#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<std::string, float> 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;
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
#ifndef _GAME_RENDER_MWSCENE_H
|
|
||||||
#define _GAME_RENDER_MWSCENE_H
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
#include <openengine/ogre/renderer.hpp>
|
|
||||||
#include <openengine/bullet/physic.hpp>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
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, distance>
|
|
||||||
/// name is empty and distance = -1 if there is no object which
|
|
||||||
/// can be faced
|
|
||||||
std::pair<std::string, float> 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
|
|
308
apps/openmw/mwrender/npcanimation.cpp
Normal file
308
apps/openmw/mwrender/npcanimation.cpp
Normal file
|
@ -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<ESM::NPC, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::NPC>();
|
||||||
|
|
||||||
|
//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<std::vector<Nif::NiTriShapeCopy>*>::iterator shapepartsiter = shapeparts.begin();
|
||||||
|
std::vector<Ogre::Entity*>::iterator entitypartsiter = entityparts.begin();
|
||||||
|
while(shapepartsiter != shapeparts.end())
|
||||||
|
{
|
||||||
|
std::vector<Nif::NiTriShapeCopy>* 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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
30
apps/openmw/mwrender/npcanimation.hpp
Normal file
30
apps/openmw/mwrender/npcanimation.hpp
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef _GAME_RENDER_NPCANIMATION_H
|
||||||
|
#define _GAME_RENDER_NPCANIMATION_H
|
||||||
|
#include "animation.hpp"
|
||||||
|
#include <components/nif/data.hpp>
|
||||||
|
#include <components/nif/node.hpp>
|
||||||
|
#include <components/nif/property.hpp>
|
||||||
|
#include <components/nif/controller.hpp>
|
||||||
|
#include <components/nif/extra.hpp>
|
||||||
|
|
||||||
|
#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
|
185
apps/openmw/mwrender/objects.cpp
Normal file
185
apps/openmw/mwrender/objects.cpp
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
#include "objects.hpp"
|
||||||
|
#include <OgreSceneNode.h>
|
||||||
|
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||||
|
|
||||||
|
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<MWWorld::Ptr::CellStore *, Ogre::SceneNode *>::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<MWWorld::RefData>& cell){
|
||||||
|
if(mSG.find(&cell) != mSG.end())
|
||||||
|
{
|
||||||
|
Ogre::StaticGeometry* sg = mSG[&cell];
|
||||||
|
sg->build();
|
||||||
|
}
|
||||||
|
}
|
48
apps/openmw/mwrender/objects.hpp
Normal file
48
apps/openmw/mwrender/objects.hpp
Normal file
|
@ -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 <openengine/ogre/renderer.hpp>
|
||||||
|
|
||||||
|
namespace MWRender{
|
||||||
|
|
||||||
|
class Objects{
|
||||||
|
OEngine::Render::OgreRenderer &mRend;
|
||||||
|
std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes;
|
||||||
|
std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> 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<MWWorld::RefData> &cell);
|
||||||
|
void setMwRoot(Ogre::SceneNode* root);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
Player::Player (Ogre::Camera *camera, const std::string& handle)
|
Player::Player (Ogre::Camera *camera, Ogre::SceneNode* node)
|
||||||
: mCamera (camera), mHandle (handle)
|
: mCamera (camera), mNode (node)
|
||||||
{}
|
{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GAME_MWRENDER_PLAYER_H
|
#define GAME_MWRENDER_PLAYER_H
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <Ogre.h>
|
||||||
|
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
|
@ -14,15 +15,16 @@ namespace MWRender
|
||||||
class Player
|
class Player
|
||||||
{
|
{
|
||||||
Ogre::Camera *mCamera;
|
Ogre::Camera *mCamera;
|
||||||
std::string mHandle;
|
Ogre::SceneNode* mNode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Player (Ogre::Camera *camera, const std::string& handle);
|
Player (Ogre::Camera *camera, Ogre::SceneNode* mNode);
|
||||||
|
|
||||||
Ogre::Camera *getCamera() { return mCamera; }
|
Ogre::Camera *getCamera() { return mCamera; }
|
||||||
|
|
||||||
std::string getHandle() const { return mHandle; }
|
std::string getHandle() const { return mNode->getName(); }
|
||||||
|
Ogre::SceneNode* getNode() {return mNode;}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
#ifndef _GAME_RENDERING_MANAGER_H
|
|
||||||
#define _GAME_RENDERING_MANAGER_H
|
|
||||||
|
|
||||||
|
|
||||||
#include "sky.hpp"
|
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
|
||||||
#include <openengine/ogre/renderer.hpp>
|
|
||||||
#include <openengine/bullet/physic.hpp>
|
|
||||||
|
|
||||||
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
|
|
16
apps/openmw/mwrender/renderinginterface.hpp
Normal file
16
apps/openmw/mwrender/renderinginterface.hpp
Normal file
|
@ -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
|
248
apps/openmw/mwrender/renderingmanager.cpp
Normal file
248
apps/openmw/mwrender/renderingmanager.cpp
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
#include "renderingmanager.hpp"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#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 <components/esm/loadstat.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
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<MWWorld::RefData> &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<MWWorld::RefData> &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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
138
apps/openmw/mwrender/renderingmanager.hpp
Normal file
138
apps/openmw/mwrender/renderingmanager.hpp
Normal file
|
@ -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 <utility>
|
||||||
|
#include <openengine/ogre/renderer.hpp>
|
||||||
|
#include <openengine/bullet/physic.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#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<MWWorld::RefData> &mCell);
|
||||||
|
/// configure fog according to cell
|
||||||
|
void configureFog(ESMS::CellStore<MWWorld::RefData> &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
|
127
apps/openmw/mwscript/animationextensions.cpp
Normal file
127
apps/openmw/mwscript/animationextensions.cpp
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
|
||||||
|
#include "animationextensions.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <components/compiler/extensions.hpp>
|
||||||
|
|
||||||
|
#include <components/interpreter/interpreter.hpp>
|
||||||
|
#include <components/interpreter/runtime.hpp>
|
||||||
|
#include <components/interpreter/opcodes.hpp>
|
||||||
|
|
||||||
|
#include "../mwworld/world.hpp"
|
||||||
|
|
||||||
|
#include "interpretercontext.hpp"
|
||||||
|
#include "ref.hpp"
|
||||||
|
|
||||||
|
namespace MWScript
|
||||||
|
{
|
||||||
|
namespace Animation
|
||||||
|
{
|
||||||
|
template<class R>
|
||||||
|
class OpSkipAnim : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
InterpreterContext& context =
|
||||||
|
static_cast<InterpreterContext&> (runtime.getContext());
|
||||||
|
|
||||||
|
context.getWorld().skipAnimation (ptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpPlayAnim : public Interpreter::Opcode1
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
InterpreterContext& context =
|
||||||
|
static_cast<InterpreterContext&> (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 R>
|
||||||
|
class OpLoopAnim : public Interpreter::Opcode1
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
InterpreterContext& context =
|
||||||
|
static_cast<InterpreterContext&> (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<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeSkipAnimExplicit, new OpSkipAnim<ExplicitRef>);
|
||||||
|
interpreter.installSegment3 (opcodePlayAnim, new OpPlayAnim<ImplicitRef>);
|
||||||
|
interpreter.installSegment3 (opcodePlayAnimExplicit, new OpPlayAnim<ExplicitRef>);
|
||||||
|
interpreter.installSegment3 (opcodeLoopAnim, new OpLoopAnim<ImplicitRef>);
|
||||||
|
interpreter.installSegment3 (opcodeLoopAnimExplicit, new OpLoopAnim<ExplicitRef>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
apps/openmw/mwscript/animationextensions.hpp
Normal file
24
apps/openmw/mwscript/animationextensions.hpp
Normal file
|
@ -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
|
|
@ -19,7 +19,11 @@ op 0x20002: AiEscort
|
||||||
op 0x20003: AiEscort, explicit reference
|
op 0x20003: AiEscort, explicit reference
|
||||||
op 0x20004: Lock
|
op 0x20004: Lock
|
||||||
op 0x20005: Lock, explicit reference
|
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:
|
Segment 4:
|
||||||
(not implemented yet)
|
(not implemented yet)
|
||||||
|
@ -109,4 +113,6 @@ op 0x2000134: SetJournalIndex
|
||||||
op 0x2000135: GetJournalIndex
|
op 0x2000135: GetJournalIndex
|
||||||
op 0x2000136: GetPCCell
|
op 0x2000136: GetPCCell
|
||||||
op 0x2000137: GetButtonPressed
|
op 0x2000137: GetButtonPressed
|
||||||
opcodes 0x2000138-0x3ffffff unused
|
op 0x2000138: SkipAnim
|
||||||
|
op 0x2000139: SkipAnim, expplicit reference
|
||||||
|
opcodes 0x200013a-0x3ffffff unused
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "aiextensions.hpp"
|
#include "aiextensions.hpp"
|
||||||
#include "controlextensions.hpp"
|
#include "controlextensions.hpp"
|
||||||
#include "dialogueextensions.hpp"
|
#include "dialogueextensions.hpp"
|
||||||
|
#include "animationextensions.hpp"
|
||||||
|
|
||||||
namespace MWScript
|
namespace MWScript
|
||||||
{
|
{
|
||||||
|
@ -29,6 +30,7 @@ namespace MWScript
|
||||||
Ai::registerExtensions (extensions);
|
Ai::registerExtensions (extensions);
|
||||||
Control::registerExtensions (extensions);
|
Control::registerExtensions (extensions);
|
||||||
Dialogue::registerExtensions (extensions);
|
Dialogue::registerExtensions (extensions);
|
||||||
|
Animation::registerExtensions (extensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
|
@ -44,5 +46,6 @@ namespace MWScript
|
||||||
Ai::installOpcodes (interpreter);
|
Ai::installOpcodes (interpreter);
|
||||||
Control::installOpcodes (interpreter);
|
Control::installOpcodes (interpreter);
|
||||||
Dialogue::installOpcodes (interpreter);
|
Dialogue::installOpcodes (interpreter);
|
||||||
|
Animation::installOpcodes (interpreter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,12 +16,12 @@ namespace MWWorld
|
||||||
/// List all (Ogre-)handles.
|
/// List all (Ogre-)handles.
|
||||||
struct ListHandles
|
struct ListHandles
|
||||||
{
|
{
|
||||||
std::vector<std::string> mHandles;
|
std::vector<Ogre::SceneNode*> mHandles;
|
||||||
|
|
||||||
bool operator() (ESM::CellRef& ref, RefData& data)
|
bool operator() (ESM::CellRef& ref, RefData& data)
|
||||||
{
|
{
|
||||||
std::string handle = data.getHandle();
|
Ogre::SceneNode* handle = data.getBaseNode();
|
||||||
if (!handle.empty())
|
if (handle)
|
||||||
mHandles.push_back (handle);
|
mHandles.push_back (handle);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,12 @@ namespace MWWorld
|
||||||
throw std::runtime_error ("class does not support ID retrieval");
|
throw std::runtime_error ("class does not support ID retrieval");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Class::insertObj (const Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
void Class::insertObjectRendering (const Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||||
MWWorld::Environment& environment) const
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
void Class::insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Class::enable (const Ptr& ptr, MWWorld::Environment& environment) const
|
void Class::enable (const Ptr& ptr, MWWorld::Environment& environment) const
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include "action.hpp"
|
#include "action.hpp"
|
||||||
#include "containerstore.hpp"
|
#include "containerstore.hpp"
|
||||||
#include "refdata.hpp"
|
#include "refdata.hpp"
|
||||||
|
#include "../mwrender/renderinginterface.hpp"
|
||||||
|
#include "physicssystem.hpp"
|
||||||
|
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
|
@ -59,8 +61,10 @@ namespace MWWorld
|
||||||
///< Return ID of \a ptr or throw an exception, if class does not support ID retrieval
|
///< Return ID of \a ptr or throw an exception, if class does not support ID retrieval
|
||||||
/// (default implementation: throw an exception)
|
/// (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).
|
///< Add reference into a cell for rendering (default implementation: don't render anything).
|
||||||
|
|
||||||
virtual void enable (const Ptr& ptr, MWWorld::Environment& environment) const;
|
virtual void enable (const Ptr& ptr, MWWorld::Environment& environment) const;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "physicssystem.hpp"
|
#include "physicssystem.hpp"
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/world.hpp" // FIXME
|
#include "../mwworld/world.hpp" // FIXME
|
||||||
|
@ -10,6 +12,7 @@
|
||||||
#include "OgreTextureManager.h"
|
#include "OgreTextureManager.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace Ogre;
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -23,6 +26,22 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
std::pair<std::string, float> 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<std::string, Ogre::Vector3> > PhysicsSystem::doPhysics (float duration,
|
std::vector< std::pair<std::string, Ogre::Vector3> > PhysicsSystem::doPhysics (float duration,
|
||||||
const std::vector<std::pair<std::string, Ogre::Vector3> >& actors)
|
const std::vector<std::pair<std::string, Ogre::Vector3> >& actors)
|
||||||
|
@ -126,6 +145,12 @@ namespace MWWorld
|
||||||
|
|
||||||
void PhysicsSystem::rotateObject (const std::string& handle, const Ogre::Quaternion& rotation)
|
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)
|
void PhysicsSystem::scaleObject (const std::string& handle, float scale)
|
||||||
|
@ -136,8 +161,11 @@ namespace MWWorld
|
||||||
bool PhysicsSystem::toggleCollisionMode()
|
bool PhysicsSystem::toggleCollisionMode()
|
||||||
{
|
{
|
||||||
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++)
|
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++)
|
||||||
|
{
|
||||||
|
if (it->first=="player")
|
||||||
{
|
{
|
||||||
OEngine::Physic::PhysicActor* act = it->second;
|
OEngine::Physic::PhysicActor* act = it->second;
|
||||||
|
|
||||||
bool cmode = act->getCollisionMode();
|
bool cmode = act->getCollisionMode();
|
||||||
if(cmode)
|
if(cmode)
|
||||||
{
|
{
|
||||||
|
@ -156,9 +184,21 @@ namespace MWWorld
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false; // This should never happen, but it shall not bother us now, since
|
throw std::logic_error ("can't find player");
|
||||||
// this part of the code needs a rewrite anyway.
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <openengine/ogre/renderer.hpp>
|
#include <openengine/ogre/renderer.hpp>
|
||||||
#include <openengine/bullet/physic.hpp>
|
#include <openengine/bullet/physic.hpp>
|
||||||
|
#include "ptr.hpp"
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
@ -32,6 +33,11 @@ namespace MWWorld
|
||||||
void scaleObject (const std::string& handle, float scale);
|
void scaleObject (const std::string& handle, float scale);
|
||||||
|
|
||||||
bool toggleCollisionMode();
|
bool toggleCollisionMode();
|
||||||
|
std::pair<std::string, float> getFacedHandle (MWWorld::World& world);
|
||||||
|
|
||||||
|
void insertObjectPhysics(const MWWorld::Ptr& ptr, std::string model);
|
||||||
|
|
||||||
|
void insertActorPhysics(const MWWorld::Ptr&, std::string model);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OEngine::Render::OgreRenderer &mRender;
|
OEngine::Render::OgreRenderer &mRender;
|
||||||
|
|
|
@ -22,7 +22,8 @@ namespace MWWorld
|
||||||
playerPos[0] = playerPos[1] = playerPos[2] = 0;
|
playerPos[0] = playerPos[1] = playerPos[2] = 0;
|
||||||
|
|
||||||
std::cout << renderer->getHandle();
|
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.
|
/// \todo Do not make a copy of classes defined in esm/p records.
|
||||||
mClass = new ESM::Class (*world.getStore().classes.find (player->cls));
|
mClass = new ESM::Class (*world.getStore().classes.find (player->cls));
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "../mwmechanics/movement.hpp"
|
#include "../mwmechanics/movement.hpp"
|
||||||
|
|
||||||
#include "containerstore.hpp"
|
#include "containerstore.hpp"
|
||||||
|
#include <Ogre.h>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
@ -22,7 +23,8 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
class RefData
|
class RefData
|
||||||
{
|
{
|
||||||
std::string mHandle;
|
Ogre::SceneNode* mBaseNode;
|
||||||
|
|
||||||
|
|
||||||
MWScript::Locals mLocals; // if we find the overhead of heaving a locals
|
MWScript::Locals mLocals; // if we find the overhead of heaving a locals
|
||||||
// object in the refdata of refs without a script,
|
// object in the refdata of refs without a script,
|
||||||
|
@ -43,16 +45,24 @@ namespace MWWorld
|
||||||
|
|
||||||
ESM::Position mPosition;
|
ESM::Position mPosition;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// @param cr Used to copy constant data such as position into this class where it can
|
/// @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
|
/// 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
|
/// 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) {}
|
mCount (1), mPosition(cr.pos) {}
|
||||||
|
|
||||||
|
|
||||||
std::string getHandle()
|
std::string getHandle()
|
||||||
{
|
{
|
||||||
return mHandle;
|
return mBaseNode->getName();
|
||||||
|
}
|
||||||
|
Ogre::SceneNode* getBaseNode(){
|
||||||
|
return mBaseNode;
|
||||||
|
}
|
||||||
|
void setBaseNode(Ogre::SceneNode* base){
|
||||||
|
mBaseNode = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getCount() const
|
int getCount() const
|
||||||
|
@ -69,10 +79,6 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setHandle (const std::string& handle)
|
|
||||||
{
|
|
||||||
mHandle = handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCount (int count)
|
void setCount (int count)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#include "scene.hpp"
|
#include "scene.hpp"
|
||||||
#include "world.hpp"
|
#include "world.hpp"
|
||||||
|
|
||||||
#include "../mwrender/interior.hpp"
|
|
||||||
#include "../mwrender/exterior.hpp"
|
|
||||||
|
|
||||||
#include "../mwmechanics/mechanicsmanager.hpp"
|
#include "../mwmechanics/mechanicsmanager.hpp"
|
||||||
|
|
||||||
|
@ -18,11 +16,13 @@
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void insertCellRefList (T& cellRefList, ESMS::CellStore<MWWorld::RefData> &cell)
|
void insertCellRefList(MWRender::RenderingManager& rendering, MWWorld::Environment& environment,
|
||||||
|
T& cellRefList, ESMS::CellStore<MWWorld::RefData> &cell, MWWorld::PhysicsSystem& physics)
|
||||||
{
|
{
|
||||||
if (!cellRefList.list.empty())
|
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();
|
for (typename T::List::iterator it = cellRefList.list.begin();
|
||||||
it != cellRefList.list.end(); it++)
|
it != cellRefList.list.end(); it++)
|
||||||
|
@ -30,11 +30,18 @@ void insertCellRefList (T& cellRefList, ESMS::CellStore<MWWorld::RefData> &cell)
|
||||||
if (it->mData.getCount() || it->mData.isEnabled())
|
if (it->mData.getCount() || it->mData.isEnabled())
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr (&*it, &cell);
|
MWWorld::Ptr ptr (&*it, &cell);
|
||||||
/* TODO: call
|
|
||||||
* RenderingManager.insertObject
|
try
|
||||||
* class_.insertObjectPhysic
|
{
|
||||||
* class_.insertObjectMechanics
|
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<MWWorld::RefData> &cell)
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
void Scene::advanceTime(){
|
||||||
void Scene::unloadCell (CellRenderCollection::iterator iter)
|
mRendering.addTime();
|
||||||
|
}
|
||||||
|
void Scene::unloadCell (CellStoreCollection::iterator iter)
|
||||||
{
|
{
|
||||||
|
std::cout << "Unloading cell\n";
|
||||||
ListHandles functor;
|
ListHandles functor;
|
||||||
iter->first->forEach<ListHandles>(functor);
|
|
||||||
|
|
||||||
{ // silence annoying g++ warning
|
MWWorld::Ptr::CellStore* active = *iter;
|
||||||
for (std::vector<std::string>::const_iterator iter (functor.mHandles.begin());
|
|
||||||
iter!=functor.mHandles.end(); ++iter)
|
|
||||||
mPhysics->removeObject (*iter);
|
|
||||||
|
|
||||||
|
active->forEach<ListHandles>(functor);
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// silence annoying g++ warning
|
||||||
|
for (std::vector<Ogre::SceneNode*>::const_iterator iter (functor.mHandles.begin());
|
||||||
|
iter!=functor.mHandles.end(); ++iter){
|
||||||
|
Ogre::SceneNode* node = *iter;
|
||||||
|
mPhysics->removeObject (node->getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mRendering.removeCell(active);
|
||||||
|
//mPhysics->removeObject("Unnamed_43");
|
||||||
|
mWorld->getLocalScripts().clearCell (active);
|
||||||
|
mEnvironment.mMechanicsManager->dropActors (active);
|
||||||
|
mEnvironment.mSoundManager->stopSound (active);
|
||||||
|
mActiveCells.erase(active);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mWorld->getLocalScripts().clearCell (iter->first);
|
void Scene::loadCell (Ptr::CellStore *cell)
|
||||||
|
|
||||||
mEnvironment.mMechanicsManager->dropActors (iter->first);
|
|
||||||
mEnvironment.mSoundManager->stopSound (iter->first);
|
|
||||||
delete iter->second;
|
|
||||||
mActiveCells.erase (iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scene::loadCell (Ptr::CellStore *cell, MWRender::CellRender *render)
|
|
||||||
{
|
{
|
||||||
// register local scripts
|
// register local scripts
|
||||||
mWorld->getLocalScripts().addCell (cell);
|
mWorld->getLocalScripts().addCell (cell);
|
||||||
|
|
||||||
// This connects the cell data with the rendering scene.
|
|
||||||
std::pair<CellRenderCollection::iterator, bool> result =
|
|
||||||
mActiveCells.insert (std::make_pair (cell, render));
|
|
||||||
|
|
||||||
if (result.second)
|
|
||||||
{
|
std::pair<CellStoreCollection::iterator, bool> result =
|
||||||
// Load the cell and insert it into the renderer
|
mActiveCells.insert(cell);
|
||||||
result.first->second->show();
|
if(result.second){
|
||||||
|
insertCell(*cell, mEnvironment);
|
||||||
|
mRendering.cellAdded (cell);
|
||||||
|
mRendering.configureAmbient(*cell);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position,
|
void Scene::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position,
|
||||||
|
@ -98,14 +122,14 @@ namespace MWWorld
|
||||||
// remove active
|
// remove active
|
||||||
mEnvironment.mMechanicsManager->removeActor (mWorld->getPlayer().getPlayer());
|
mEnvironment.mMechanicsManager->removeActor (mWorld->getPlayer().getPlayer());
|
||||||
|
|
||||||
CellRenderCollection::iterator active = mActiveCells.begin();
|
CellStoreCollection::iterator active = mActiveCells.begin();
|
||||||
|
|
||||||
while (active!=mActiveCells.end())
|
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 &&
|
if (std::abs (X-(*active)->cell->data.gridX)<=1 &&
|
||||||
std::abs (Y-active->first->cell->data.gridY)<=1)
|
std::abs (Y-(*active)->cell->data.gridY)<=1)
|
||||||
{
|
{
|
||||||
// keep cells within the new 3x3 grid
|
// keep cells within the new 3x3 grid
|
||||||
++active;
|
++active;
|
||||||
|
@ -120,14 +144,14 @@ namespace MWWorld
|
||||||
for (int x=X-1; x<=X+1; ++x)
|
for (int x=X-1; x<=X+1; ++x)
|
||||||
for (int y=Y-1; y<=Y+1; ++y)
|
for (int y=Y-1; y<=Y+1; ++y)
|
||||||
{
|
{
|
||||||
CellRenderCollection::iterator iter = mActiveCells.begin();
|
CellStoreCollection::iterator iter = mActiveCells.begin();
|
||||||
|
|
||||||
while (iter!=mActiveCells.end())
|
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 &&
|
if (x==(*iter)->cell->data.gridX &&
|
||||||
y==iter->first->cell->data.gridY)
|
y==(*iter)->cell->data.gridY)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
++iter;
|
++iter;
|
||||||
|
@ -137,19 +161,19 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
Ptr::CellStore *cell = mWorld->getExterior(x, y);
|
Ptr::CellStore *cell = mWorld->getExterior(x, y);
|
||||||
|
|
||||||
loadCell (cell, new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene, mPhysics));
|
loadCell (cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// find current cell
|
// find current cell
|
||||||
CellRenderCollection::iterator iter = mActiveCells.begin();
|
CellStoreCollection::iterator iter = mActiveCells.begin();
|
||||||
|
|
||||||
while (iter!=mActiveCells.end())
|
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 &&
|
if (X==(*iter)->cell->data.gridX &&
|
||||||
Y==iter->first->cell->data.gridY)
|
Y==(*iter)->cell->data.gridY)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
++iter;
|
++iter;
|
||||||
|
@ -157,7 +181,7 @@ namespace MWWorld
|
||||||
|
|
||||||
assert (iter!=mActiveCells.end());
|
assert (iter!=mActiveCells.end());
|
||||||
|
|
||||||
mCurrentCell = iter->first;
|
mCurrentCell = *iter;
|
||||||
|
|
||||||
// adjust player
|
// adjust player
|
||||||
playerCellChange (mWorld->getExterior(X, Y), position, adjustPlayerPos);
|
playerCellChange (mWorld->getExterior(X, Y), position, adjustPlayerPos);
|
||||||
|
@ -168,17 +192,15 @@ namespace MWWorld
|
||||||
mCellChanged = true;
|
mCellChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene::Scene (Environment& environment, World *world, MWRender::MWScene& scene, PhysicsSystem *physics)
|
//We need the ogre renderer and a scene node.
|
||||||
: mScene (scene), mCurrentCell (0),
|
Scene::Scene (Environment& environment, World *world, MWRender::RenderingManager& rendering, PhysicsSystem *physics)
|
||||||
mCellChanged (false), mEnvironment (environment), mWorld(world), mPhysics(physics)
|
: mCurrentCell (0), mCellChanged (false), mEnvironment (environment), mWorld(world),
|
||||||
|
mPhysics(physics), mRendering(rendering)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene::~Scene()
|
Scene::~Scene()
|
||||||
{
|
{
|
||||||
for (CellRenderCollection::iterator iter (mActiveCells.begin());
|
|
||||||
iter!=mActiveCells.end(); ++iter)
|
|
||||||
delete iter->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Scene::hasCellChanged() const
|
bool Scene::hasCellChanged() const
|
||||||
|
@ -186,15 +208,16 @@ namespace MWWorld
|
||||||
return mCellChanged;
|
return mCellChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Scene::CellRenderCollection& Scene::getActiveCells() const
|
const Scene::CellStoreCollection& Scene::getActiveCells() const
|
||||||
{
|
{
|
||||||
return mActiveCells;
|
return mActiveCells;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position)
|
void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position)
|
||||||
{
|
{
|
||||||
|
std::cout << "Changing to interior\n";
|
||||||
// remove active
|
// remove active
|
||||||
CellRenderCollection::iterator active = mActiveCells.begin();
|
CellStoreCollection::iterator active = mActiveCells.begin();
|
||||||
|
|
||||||
while (active!=mActiveCells.end())
|
while (active!=mActiveCells.end())
|
||||||
{
|
{
|
||||||
|
@ -205,7 +228,7 @@ namespace MWWorld
|
||||||
std::cout << "cellName:" << cellName << std::endl;
|
std::cout << "cellName:" << cellName << std::endl;
|
||||||
Ptr::CellStore *cell = mWorld->getInterior(cellName);
|
Ptr::CellStore *cell = mWorld->getInterior(cellName);
|
||||||
|
|
||||||
loadCell (cell, new MWRender::InteriorCellRender (*cell, mEnvironment, mScene, mPhysics));
|
loadCell (cell);
|
||||||
|
|
||||||
// adjust player
|
// adjust player
|
||||||
mCurrentCell = cell;
|
mCurrentCell = cell;
|
||||||
|
@ -215,7 +238,6 @@ namespace MWWorld
|
||||||
mWorld->adjustSky();
|
mWorld->adjustSky();
|
||||||
|
|
||||||
mCellChanged = true;
|
mCellChanged = true;
|
||||||
//currentRegion->name = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::changeToExteriorCell (const ESM::Position& position)
|
void Scene::changeToExteriorCell (const ESM::Position& position)
|
||||||
|
@ -238,36 +260,31 @@ namespace MWWorld
|
||||||
mCellChanged = false;
|
mCellChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*#include <cassert>
|
void Scene::insertCell(ESMS::CellStore<MWWorld::RefData> &cell,
|
||||||
#include <iostream>
|
MWWorld::Environment& environment)
|
||||||
#include <exception>
|
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
|
||||||
#include "../mwworld/ptr.hpp"*/
|
|
||||||
|
|
||||||
void Scene::insertCell(ESMS::CellStore<MWWorld::RefData> &cell)
|
|
||||||
{
|
{
|
||||||
// Loop through all references in the cell
|
// Loop through all references in the cell
|
||||||
insertCellRefList (cell.activators, cell);
|
insertCellRefList(mRendering, environment, cell.activators, cell, *mPhysics);
|
||||||
insertCellRefList (cell.potions, cell);
|
insertCellRefList(mRendering, environment, cell.potions, cell, *mPhysics);
|
||||||
insertCellRefList (cell.appas, cell);
|
insertCellRefList(mRendering, environment, cell.appas, cell, *mPhysics);
|
||||||
insertCellRefList (cell.armors, cell);
|
insertCellRefList(mRendering, environment, cell.armors, cell, *mPhysics);
|
||||||
insertCellRefList (cell.books, cell);
|
insertCellRefList(mRendering, environment, cell.books, cell, *mPhysics);
|
||||||
insertCellRefList (cell.clothes, cell);
|
insertCellRefList(mRendering, environment, cell.clothes, cell, *mPhysics);
|
||||||
insertCellRefList (cell.containers, cell);
|
insertCellRefList(mRendering, environment, cell.containers, cell, *mPhysics);
|
||||||
insertCellRefList (cell.creatures, cell);
|
insertCellRefList(mRendering, environment, cell.creatures, cell, *mPhysics);
|
||||||
insertCellRefList (cell.doors, cell);
|
insertCellRefList(mRendering, environment, cell.doors, cell, *mPhysics);
|
||||||
insertCellRefList (cell.ingreds, cell);
|
insertCellRefList(mRendering, environment, cell.ingreds, cell, *mPhysics);
|
||||||
insertCellRefList (cell.creatureLists, cell);
|
insertCellRefList(mRendering, environment, cell.creatureLists, cell, *mPhysics);
|
||||||
insertCellRefList (cell.itemLists, cell);
|
insertCellRefList(mRendering, environment, cell.itemLists, cell, *mPhysics);
|
||||||
insertCellRefList (cell.lights, cell);
|
insertCellRefList(mRendering, environment, cell.lights, cell, *mPhysics);
|
||||||
insertCellRefList (cell.lockpicks, cell);
|
insertCellRefList(mRendering, environment, cell.lockpicks, cell, *mPhysics);
|
||||||
insertCellRefList (cell.miscItems, cell);
|
insertCellRefList(mRendering, environment, cell.miscItems, cell, *mPhysics);
|
||||||
insertCellRefList (cell.npcs, cell);
|
insertCellRefList(mRendering, environment, cell.npcs, cell, *mPhysics);
|
||||||
insertCellRefList (cell.probes, cell);
|
insertCellRefList(mRendering, environment, cell.probes, cell, *mPhysics);
|
||||||
insertCellRefList (cell.repairs, cell);
|
insertCellRefList(mRendering, environment, cell.repairs, cell, *mPhysics);
|
||||||
insertCellRefList (cell.statics, cell);
|
insertCellRefList(mRendering, environment, cell.statics, cell, *mPhysics);
|
||||||
insertCellRefList (cell.weapons, cell);
|
insertCellRefList(mRendering, environment, cell.weapons, cell, *mPhysics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,17 +6,18 @@
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#include <openengine/bullet/physic.hpp>
|
||||||
|
|
||||||
#include <components/esm_store/cell_store.hpp>
|
#include <components/esm_store/cell_store.hpp>
|
||||||
|
|
||||||
#include "../mwrender/mwscene.hpp"
|
#include "../mwrender/renderingmanager.hpp"
|
||||||
#include "physicssystem.hpp"
|
#include "../mwrender/renderinginterface.hpp"
|
||||||
|
|
||||||
|
#include "physicssystem.hpp"
|
||||||
#include "refdata.hpp"
|
#include "refdata.hpp"
|
||||||
#include "ptr.hpp"
|
#include "ptr.hpp"
|
||||||
#include "globals.hpp"
|
#include "globals.hpp"
|
||||||
|
|
||||||
#include <openengine/bullet/physic.hpp>
|
|
||||||
|
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
class Vector3;
|
class Vector3;
|
||||||
|
@ -53,29 +54,32 @@ namespace MWWorld
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::map<Ptr::CellStore *, MWRender::CellRender *> CellRenderCollection;
|
typedef std::set<Ptr::CellStore *> CellStoreCollection;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
MWRender::MWScene& mScene;
|
//OEngine::Render::OgreRenderer& mRenderer;
|
||||||
Ptr::CellStore *mCurrentCell; // the cell, the player is in
|
Ptr::CellStore* mCurrentCell; // the cell, the player is in
|
||||||
CellRenderCollection mActiveCells;
|
CellStoreCollection mActiveCells;
|
||||||
bool mCellChanged;
|
bool mCellChanged;
|
||||||
Environment& mEnvironment;
|
Environment& mEnvironment;
|
||||||
World *mWorld;
|
World *mWorld;
|
||||||
PhysicsSystem *mPhysics;
|
PhysicsSystem *mPhysics;
|
||||||
|
MWRender::RenderingManager& mRendering;
|
||||||
|
|
||||||
void playerCellChange (Ptr::CellStore *cell, const ESM::Position& position,
|
void playerCellChange (Ptr::CellStore *cell, const ESM::Position& position,
|
||||||
bool adjustPlayerPos = true);
|
bool adjustPlayerPos = true);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Scene (Environment& environment, World *world, MWRender::MWScene& scene, PhysicsSystem *physics);
|
Scene (Environment& environment, World *world, MWRender::RenderingManager& rendering, PhysicsSystem *physics);
|
||||||
|
|
||||||
~Scene();
|
~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);
|
void changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos);
|
||||||
///< Move from exterior to interior or from interior cell to a different
|
///< Move from exterior to interior or from interior cell to a different
|
||||||
|
@ -83,7 +87,7 @@ namespace MWWorld
|
||||||
|
|
||||||
Ptr::CellStore* getCurrentCell ();
|
Ptr::CellStore* getCurrentCell ();
|
||||||
|
|
||||||
const CellRenderCollection& getActiveCells () const;
|
const CellStoreCollection& getActiveCells () const;
|
||||||
|
|
||||||
bool hasCellChanged() const;
|
bool hasCellChanged() const;
|
||||||
///< Has the player moved to a different cell, since the last frame?
|
///< Has the player moved to a different cell, since the last frame?
|
||||||
|
@ -96,9 +100,8 @@ namespace MWWorld
|
||||||
|
|
||||||
void markCellAsUnchanged();
|
void markCellAsUnchanged();
|
||||||
|
|
||||||
// std::string getFacedHandle();
|
void insertCell(ESMS::CellStore<MWWorld::RefData> &cell, MWWorld::Environment& environment);
|
||||||
|
void advanceTime();
|
||||||
void insertCell(ESMS::CellStore<MWWorld::RefData> &cell);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
#include <components/files/collections.hpp>
|
#include <components/files/collections.hpp>
|
||||||
|
|
||||||
#include "../mwrender/sky.hpp"
|
#include "../mwrender/sky.hpp"
|
||||||
#include "../mwrender/interior.hpp"
|
#include "../mwrender/player.hpp"
|
||||||
#include "../mwrender/exterior.hpp"
|
|
||||||
|
|
||||||
#include "../mwmechanics/mechanicsmanager.hpp"
|
#include "../mwmechanics/mechanicsmanager.hpp"
|
||||||
|
|
||||||
|
@ -54,12 +53,13 @@ namespace
|
||||||
|
|
||||||
for (iterator iter (refList.list.begin()); iter!=refList.list.end(); ++iter)
|
for (iterator iter (refList.list.begin()); iter!=refList.list.end(); ++iter)
|
||||||
{
|
{
|
||||||
|
if(iter->mData.getBaseNode()){
|
||||||
if (iter->mData.getHandle()==handle)
|
if (iter->mData.getHandle()==handle)
|
||||||
{
|
{
|
||||||
return &*iter;
|
return &*iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,75 +71,46 @@ namespace MWWorld
|
||||||
if (ESMS::LiveCellRef<ESM::Activator, RefData> *ref =
|
if (ESMS::LiveCellRef<ESM::Activator, RefData> *ref =
|
||||||
searchViaHandle (handle, cell.activators))
|
searchViaHandle (handle, cell.activators))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Potion, RefData> *ref = searchViaHandle (handle, cell.potions))
|
if (ESMS::LiveCellRef<ESM::Potion, RefData> *ref = searchViaHandle (handle, cell.potions))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Apparatus, RefData> *ref = searchViaHandle (handle, cell.appas))
|
if (ESMS::LiveCellRef<ESM::Apparatus, RefData> *ref = searchViaHandle (handle, cell.appas))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Armor, RefData> *ref = searchViaHandle (handle, cell.armors))
|
if (ESMS::LiveCellRef<ESM::Armor, RefData> *ref = searchViaHandle (handle, cell.armors))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Book, RefData> *ref = searchViaHandle (handle, cell.books))
|
if (ESMS::LiveCellRef<ESM::Book, RefData> *ref = searchViaHandle (handle, cell.books))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Clothing, RefData> *ref = searchViaHandle (handle, cell.clothes))
|
if (ESMS::LiveCellRef<ESM::Clothing, RefData> *ref = searchViaHandle (handle, cell.clothes))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Container, RefData> *ref =
|
if (ESMS::LiveCellRef<ESM::Container, RefData> *ref =
|
||||||
searchViaHandle (handle, cell.containers))
|
searchViaHandle (handle, cell.containers))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Creature, RefData> *ref =
|
if (ESMS::LiveCellRef<ESM::Creature, RefData> *ref =
|
||||||
searchViaHandle (handle, cell.creatures))
|
searchViaHandle (handle, cell.creatures))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Door, RefData> *ref = searchViaHandle (handle, cell.doors))
|
if (ESMS::LiveCellRef<ESM::Door, RefData> *ref = searchViaHandle (handle, cell.doors))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Ingredient, RefData> *ref =
|
if (ESMS::LiveCellRef<ESM::Ingredient, RefData> *ref =
|
||||||
searchViaHandle (handle, cell.ingreds))
|
searchViaHandle (handle, cell.ingreds))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Light, RefData> *ref = searchViaHandle (handle, cell.lights))
|
if (ESMS::LiveCellRef<ESM::Light, RefData> *ref = searchViaHandle (handle, cell.lights))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Tool, RefData> *ref = searchViaHandle (handle, cell.lockpicks))
|
if (ESMS::LiveCellRef<ESM::Tool, RefData> *ref = searchViaHandle (handle, cell.lockpicks))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Miscellaneous, RefData> *ref = searchViaHandle (handle, cell.miscItems))
|
if (ESMS::LiveCellRef<ESM::Miscellaneous, RefData> *ref = searchViaHandle (handle, cell.miscItems))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::NPC, RefData> *ref = searchViaHandle (handle, cell.npcs))
|
if (ESMS::LiveCellRef<ESM::NPC, RefData> *ref = searchViaHandle (handle, cell.npcs))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Probe, RefData> *ref = searchViaHandle (handle, cell.probes))
|
if (ESMS::LiveCellRef<ESM::Probe, RefData> *ref = searchViaHandle (handle, cell.probes))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Repair, RefData> *ref = searchViaHandle (handle, cell.repairs))
|
if (ESMS::LiveCellRef<ESM::Repair, RefData> *ref = searchViaHandle (handle, cell.repairs))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Static, RefData> *ref = searchViaHandle (handle, cell.statics))
|
if (ESMS::LiveCellRef<ESM::Static, RefData> *ref = searchViaHandle (handle, cell.statics))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
if (ESMS::LiveCellRef<ESM::Weapon, RefData> *ref = searchViaHandle (handle, cell.weapons))
|
if (ESMS::LiveCellRef<ESM::Weapon, RefData> *ref = searchViaHandle (handle, cell.weapons))
|
||||||
return Ptr (ref, &cell);
|
return Ptr (ref, &cell);
|
||||||
|
|
||||||
return Ptr();
|
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
|
int World::getDaysPerMonth (int month) const
|
||||||
{
|
{
|
||||||
|
@ -176,7 +147,7 @@ namespace MWWorld
|
||||||
const Files::Collections& fileCollections,
|
const Files::Collections& fileCollections,
|
||||||
const std::string& master, const boost::filesystem::path& resDir,
|
const std::string& master, const boost::filesystem::path& resDir,
|
||||||
bool newGame, Environment& environment, const std::string& encoding)
|
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)
|
mSky (false), mEnvironment (environment), mNextDynamicRecord (0), mCells (mStore, mEsm, *this)
|
||||||
{
|
{
|
||||||
mPhysEngine = physEng;
|
mPhysEngine = physEng;
|
||||||
|
@ -192,7 +163,8 @@ namespace MWWorld
|
||||||
mEsm.open (masterPath.string());
|
mEsm.open (masterPath.string());
|
||||||
mStore.load (mEsm);
|
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));
|
mPhysics->addActor (mPlayer->getPlayer().getRefData().getHandle(), "", Ogre::Vector3 (0, 0, 0));
|
||||||
|
|
||||||
// global variables
|
// global variables
|
||||||
|
@ -206,18 +178,18 @@ namespace MWWorld
|
||||||
|
|
||||||
mPhysEngine = physEng;
|
mPhysEngine = physEng;
|
||||||
|
|
||||||
mWorldScene = new Scene(environment, this, mScene, mPhysics);
|
mWorldScene = new Scene(environment, this, mRendering, mPhysics);
|
||||||
mRenderingManager = new MWRender::RenderingManager(
|
|
||||||
MWRender::SkyManager::create(renderer.getWindow(), mScene.getCamera(), resDir)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
World::~World()
|
World::~World()
|
||||||
{
|
{
|
||||||
delete mWorldScene;
|
delete mWorldScene;
|
||||||
delete mGlobalVariables;
|
delete mGlobalVariables;
|
||||||
delete mPlayer;
|
|
||||||
delete mPhysics;
|
delete mPhysics;
|
||||||
|
|
||||||
|
delete mPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ESM::Cell *World::getExterior (const std::string& cellName) const
|
const ESM::Cell *World::getExterior (const std::string& cellName) const
|
||||||
|
@ -303,10 +275,11 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
// active cells
|
// 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)
|
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())
|
if (!ptr.isEmpty())
|
||||||
return ptr;
|
return ptr;
|
||||||
|
@ -327,11 +300,11 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
if (mPlayer->getPlayer().getRefData().getHandle()==handle)
|
if (mPlayer->getPlayer().getRefData().getHandle()==handle)
|
||||||
return mPlayer->getPlayer();
|
return mPlayer->getPlayer();
|
||||||
|
for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin());
|
||||||
for (Scene::CellRenderCollection::const_iterator iter (mWorldScene->getActiveCells().begin());
|
|
||||||
iter!=mWorldScene->getActiveCells().end(); ++iter)
|
iter!=mWorldScene->getActiveCells().end(); ++iter)
|
||||||
{
|
{
|
||||||
Ptr ptr = getPtrViaHandle (handle, *iter->first);
|
Ptr::CellStore* cellstore = *iter;
|
||||||
|
Ptr ptr = getPtrViaHandle (handle, *cellstore);
|
||||||
|
|
||||||
if (!ptr.isEmpty())
|
if (!ptr.isEmpty())
|
||||||
return ptr;
|
return ptr;
|
||||||
|
@ -346,13 +319,12 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
reference.getRefData().enable();
|
reference.getRefData().enable();
|
||||||
|
|
||||||
if (MWRender::CellRender *render = searchRender (reference.getCell()))
|
|
||||||
{
|
|
||||||
render->enable (reference.getRefData().getHandle());
|
|
||||||
|
|
||||||
if (mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end())
|
//render->enable (reference.getRefData().getHandle());
|
||||||
|
if(mWorldScene->getActiveCells().find (reference.getCell()) != mWorldScene->getActiveCells().end())
|
||||||
Class::get (reference).enable (reference, mEnvironment);
|
Class::get (reference).enable (reference, mEnvironment);
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,16 +334,14 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
reference.getRefData().disable();
|
reference.getRefData().disable();
|
||||||
|
|
||||||
if (MWRender::CellRender *render = searchRender (reference.getCell()))
|
|
||||||
{
|
|
||||||
render->disable (reference.getRefData().getHandle());
|
|
||||||
|
|
||||||
if (mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end())
|
//render->disable (reference.getRefData().getHandle());
|
||||||
{
|
if(mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end()){
|
||||||
Class::get (reference).disable (reference, mEnvironment);
|
Class::get (reference).disable (reference, mEnvironment);
|
||||||
mEnvironment.mSoundManager->stopSound3D (reference);
|
mEnvironment.mSoundManager->stopSound3D (reference);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,6 +355,7 @@ namespace MWWorld
|
||||||
|
|
||||||
if (days>0)
|
if (days>0)
|
||||||
mGlobalVariables->setInt ("dayspassed", days + mGlobalVariables->getInt ("dayspassed"));
|
mGlobalVariables->setInt ("dayspassed", days + mGlobalVariables->getInt ("dayspassed"));
|
||||||
|
mWorldScene->advanceTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::setHour (double hour)
|
void World::setHour (double hour)
|
||||||
|
@ -398,7 +369,7 @@ namespace MWWorld
|
||||||
|
|
||||||
mGlobalVariables->setFloat ("gamehour", hour);
|
mGlobalVariables->setFloat ("gamehour", hour);
|
||||||
|
|
||||||
mRenderingManager->skySetHour (hour);
|
mRendering.skySetHour (hour);
|
||||||
|
|
||||||
if (days>0)
|
if (days>0)
|
||||||
setDay (days + mGlobalVariables->getInt ("day"));
|
setDay (days + mGlobalVariables->getInt ("day"));
|
||||||
|
@ -433,7 +404,7 @@ namespace MWWorld
|
||||||
mGlobalVariables->setInt ("day", day);
|
mGlobalVariables->setInt ("day", day);
|
||||||
mGlobalVariables->setInt ("month", month);
|
mGlobalVariables->setInt ("month", month);
|
||||||
|
|
||||||
mRenderingManager->skySetDate (day, month);
|
mRendering.skySetDate (day, month);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::setMonth (int month)
|
void World::setMonth (int month)
|
||||||
|
@ -454,7 +425,7 @@ namespace MWWorld
|
||||||
if (years>0)
|
if (years>0)
|
||||||
mGlobalVariables->setInt ("year", years+mGlobalVariables->getInt ("year"));
|
mGlobalVariables->setInt ("year", years+mGlobalVariables->getInt ("year"));
|
||||||
|
|
||||||
mRenderingManager->skySetDate (mGlobalVariables->getInt ("day"), month);
|
mRendering.skySetDate (mGlobalVariables->getInt ("day"), month);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::toggleSky()
|
bool World::toggleSky()
|
||||||
|
@ -462,34 +433,34 @@ namespace MWWorld
|
||||||
if (mSky)
|
if (mSky)
|
||||||
{
|
{
|
||||||
mSky = false;
|
mSky = false;
|
||||||
mRenderingManager->skyDisable();
|
mRendering.skyDisable();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mSky = true;
|
mSky = true;
|
||||||
// TODO check for extorior or interior with sky.
|
// TODO check for extorior or interior with sky.
|
||||||
mRenderingManager->skySetHour (mGlobalVariables->getFloat ("gamehour"));
|
mRendering.skySetHour (mGlobalVariables->getFloat ("gamehour"));
|
||||||
mRenderingManager->skySetDate (mGlobalVariables->getInt ("day"),
|
mRendering.skySetDate (mGlobalVariables->getInt ("day"),
|
||||||
mGlobalVariables->getInt ("month"));
|
mGlobalVariables->getInt ("month"));
|
||||||
mRenderingManager->skyEnable();
|
mRendering.skyEnable();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int World::getMasserPhase() const
|
int World::getMasserPhase() const
|
||||||
{
|
{
|
||||||
return mRenderingManager->skyGetMasserPhase();
|
return mRendering.skyGetMasserPhase();
|
||||||
}
|
}
|
||||||
|
|
||||||
int World::getSecundaPhase() const
|
int World::getSecundaPhase() const
|
||||||
{
|
{
|
||||||
return mRenderingManager->skyGetSecundaPhase();
|
return mRendering.skyGetSecundaPhase();
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::setMoonColour (bool red)
|
void World::setMoonColour (bool red)
|
||||||
{
|
{
|
||||||
mRenderingManager->skySetMoonColour (red);
|
mRendering.skySetMoonColour (red);
|
||||||
}
|
}
|
||||||
|
|
||||||
float World::getTimeScaleFactor() const
|
float World::getTimeScaleFactor() const
|
||||||
|
@ -514,7 +485,7 @@ namespace MWWorld
|
||||||
|
|
||||||
std::string World::getFacedHandle()
|
std::string World::getFacedHandle()
|
||||||
{
|
{
|
||||||
std::pair<std::string, float> result = mScene.getFacedHandle (*this);
|
std::pair<std::string, float> result = mPhysics->getFacedHandle (*this);
|
||||||
|
|
||||||
if (result.first.empty() ||
|
if (result.first.empty() ||
|
||||||
result.second>getStore().gameSettings.find ("iMaxActivateDist")->i)
|
result.second>getStore().gameSettings.find ("iMaxActivateDist")->i)
|
||||||
|
@ -529,21 +500,16 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
ptr.getRefData().setCount (0);
|
ptr.getRefData().setCount (0);
|
||||||
|
|
||||||
if (MWRender::CellRender *render = searchRender (ptr.getCell()))
|
|
||||||
{
|
if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end()){
|
||||||
if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end())
|
// Class::get (ptr).disable (ptr, mEnvironment); /// \todo this line needs to be removed
|
||||||
{
|
|
||||||
Class::get (ptr).disable (ptr, mEnvironment);
|
|
||||||
mEnvironment.mSoundManager->stopSound3D (ptr);
|
mEnvironment.mSoundManager->stopSound3D (ptr);
|
||||||
|
|
||||||
mPhysics->removeObject (ptr.getRefData().getHandle());
|
mPhysics->removeObject (ptr.getRefData().getHandle());
|
||||||
|
mRendering.removeObject(ptr);
|
||||||
|
|
||||||
mLocalScripts.remove (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.
|
mRendering.moveObject (ptr, Ogre::Vector3 (x, y, z));
|
||||||
mScene.getMgr()->getSceneNode (ptr.getRefData().getHandle())->
|
|
||||||
setPosition (Ogre::Vector3 (x, y, z));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::moveObject (Ptr ptr, float x, float y, float z)
|
void World::moveObject (Ptr ptr, float x, float y, float z)
|
||||||
|
@ -653,7 +617,7 @@ namespace MWWorld
|
||||||
|
|
||||||
bool World::toggleRenderMode (RenderMode mode)
|
bool World::toggleRenderMode (RenderMode mode)
|
||||||
{
|
{
|
||||||
return mScene.toggleRenderMode (mode);
|
return mRendering.toggleRenderMode (mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<std::string, const ESM::Potion *> World::createRecord (const ESM::Potion& record)
|
std::pair<std::string, const ESM::Potion *> World::createRecord (const ESM::Potion& record)
|
||||||
|
@ -710,4 +674,21 @@ namespace MWWorld
|
||||||
return cell;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
|
|
||||||
#include <components/esm_store/cell_store.hpp>
|
#include <components/esm_store/cell_store.hpp>
|
||||||
|
|
||||||
#include "../mwrender/mwscene.hpp"
|
#include "../mwrender/debugging.hpp"
|
||||||
#include "../mwrender/rendering_manager.hpp"
|
#include "../mwrender/renderingmanager.hpp"
|
||||||
|
|
||||||
#include "refdata.hpp"
|
#include "refdata.hpp"
|
||||||
#include "ptr.hpp"
|
#include "ptr.hpp"
|
||||||
|
@ -65,7 +65,8 @@ namespace MWWorld
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
MWRender::MWScene mScene;
|
MWRender::RenderingManager mRendering;
|
||||||
|
|
||||||
MWWorld::Scene *mWorldScene;
|
MWWorld::Scene *mWorldScene;
|
||||||
MWWorld::Player *mPlayer;
|
MWWorld::Player *mPlayer;
|
||||||
ESM::ESMReader mEsm;
|
ESM::ESMReader mEsm;
|
||||||
|
@ -75,7 +76,6 @@ namespace MWWorld
|
||||||
MWWorld::PhysicsSystem *mPhysics;
|
MWWorld::PhysicsSystem *mPhysics;
|
||||||
bool mSky;
|
bool mSky;
|
||||||
Environment& mEnvironment;
|
Environment& mEnvironment;
|
||||||
MWRender::RenderingManager *mRenderingManager;
|
|
||||||
int mNextDynamicRecord;
|
int mNextDynamicRecord;
|
||||||
|
|
||||||
Cells mCells;
|
Cells mCells;
|
||||||
|
@ -88,7 +88,6 @@ namespace MWWorld
|
||||||
|
|
||||||
Ptr getPtrViaHandle (const std::string& handle, Ptr::CellStore& cellStore);
|
Ptr getPtrViaHandle (const std::string& handle, Ptr::CellStore& cellStore);
|
||||||
|
|
||||||
MWRender::CellRender *searchRender (Ptr::CellStore *store);
|
|
||||||
|
|
||||||
int getDaysPerMonth (int month) const;
|
int getDaysPerMonth (int month) const;
|
||||||
|
|
||||||
|
@ -134,8 +133,10 @@ namespace MWWorld
|
||||||
Ptr getPtrViaHandle (const std::string& handle);
|
Ptr getPtrViaHandle (const std::string& handle);
|
||||||
///< Return a pointer to a liveCellRef with the given Ogre handle.
|
///< Return a pointer to a liveCellRef with the given Ogre handle.
|
||||||
|
|
||||||
|
/// \todo enable reference in the OGRE scene
|
||||||
void enable (Ptr reference);
|
void enable (Ptr reference);
|
||||||
|
|
||||||
|
/// \todo 5disable reference in the OGRE scene
|
||||||
void disable (Ptr reference);
|
void disable (Ptr reference);
|
||||||
|
|
||||||
void advanceTime (double hours);
|
void advanceTime (double hours);
|
||||||
|
@ -205,6 +206,20 @@ namespace MWWorld
|
||||||
const ESM::Cell *createRecord (const ESM::Cell& record);
|
const ESM::Cell *createRecord (const ESM::Cell& record);
|
||||||
///< Create a new recrod (of type cell) in the ESM store.
|
///< Create a new recrod (of type cell) in the ESM store.
|
||||||
/// \return ID, pointer to created record
|
/// \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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -240,15 +240,36 @@ public:
|
||||||
// should not have been declared const in the first place.
|
// should not have been declared const in the first place.
|
||||||
BSAFile *narc = (BSAFile*)&arc;
|
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
|
// Open the file
|
||||||
StreamPtr strm = narc->getFile(filename.c_str());
|
StreamPtr strm = narc->getFile(passed.c_str());
|
||||||
|
|
||||||
// Wrap it into an Ogre::DataStream.
|
// Wrap it into an Ogre::DataStream.
|
||||||
return DataStreamPtr(new Mangle2OgreStream(strm));
|
return DataStreamPtr(new Mangle2OgreStream(strm));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the file exists.
|
// 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; }
|
time_t getModifiedTime(const String&) { return 0; }
|
||||||
|
|
||||||
// This is never called as far as I can see.
|
// This is never called as far as I can see.
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include "controlled.hpp"
|
#include "controlled.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <Ogre.h>
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
@ -366,6 +367,12 @@ public:
|
||||||
Vector trans; // Translation
|
Vector trans; // Translation
|
||||||
float scale; // Probably scale (always 1)
|
float scale; // Probably scale (always 1)
|
||||||
};
|
};
|
||||||
|
struct BoneTrafoCopy
|
||||||
|
{
|
||||||
|
Ogre::Quaternion rotation;
|
||||||
|
Ogre::Vector3 trans;
|
||||||
|
float scale;
|
||||||
|
};
|
||||||
|
|
||||||
struct VertWeight
|
struct VertWeight
|
||||||
{
|
{
|
||||||
|
@ -380,6 +387,19 @@ public:
|
||||||
const Vector4 *unknown;
|
const Vector4 *unknown;
|
||||||
Misc::SliceArray<VertWeight> weights;
|
Misc::SliceArray<VertWeight> weights;
|
||||||
};
|
};
|
||||||
|
struct BoneInfoCopy
|
||||||
|
{
|
||||||
|
std::string bonename;
|
||||||
|
unsigned short bonehandle;
|
||||||
|
BoneTrafoCopy trafo;
|
||||||
|
Vector4 unknown;
|
||||||
|
//std::vector<VertWeight> weights;
|
||||||
|
};
|
||||||
|
struct IndividualWeight
|
||||||
|
{
|
||||||
|
float weight;
|
||||||
|
unsigned int boneinfocopyindex;
|
||||||
|
};
|
||||||
|
|
||||||
const BoneTrafo *trafo;
|
const BoneTrafo *trafo;
|
||||||
std::vector<BoneInfo> bones;
|
std::vector<BoneInfo> bones;
|
||||||
|
@ -412,43 +432,213 @@ public:
|
||||||
|
|
||||||
class NiMorphData : public Record
|
class NiMorphData : public Record
|
||||||
{
|
{
|
||||||
|
float startTime;
|
||||||
|
float stopTime;
|
||||||
|
std::vector<Ogre::Vector3> initialVertices;
|
||||||
|
std::vector<std::vector<float> > relevantTimes;
|
||||||
|
std::vector<std::vector<Ogre::Vector3> > relevantData;
|
||||||
|
std::vector<std::vector<Ogre::Vector3> > additionalVertices;
|
||||||
|
|
||||||
|
|
||||||
public:
|
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<Ogre::Vector3> getInitialVertices(){
|
||||||
|
return initialVertices;
|
||||||
|
}
|
||||||
|
std::vector<std::vector<Ogre::Vector3> > getRelevantData(){
|
||||||
|
return relevantData;
|
||||||
|
}
|
||||||
|
std::vector<std::vector<float> > getRelevantTimes(){
|
||||||
|
return relevantTimes;
|
||||||
|
}
|
||||||
|
std::vector<std::vector<Ogre::Vector3> > getAdditionalVertices(){
|
||||||
|
return additionalVertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
int morphCount = nif->getInt();
|
int morphCount = nif->getInt();
|
||||||
int vertCount = nif->getInt();
|
int vertCount = nif->getInt();
|
||||||
nif->getByte();
|
nif->getByte();
|
||||||
|
|
||||||
for(int i=0; i<morphCount; i++)
|
|
||||||
{
|
|
||||||
int magic = nif->getInt();
|
int magic = nif->getInt();
|
||||||
nif->getInt();
|
int type = nif->getInt();
|
||||||
if(magic)
|
for(int i = 0; i < vertCount; i++){
|
||||||
// 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; i<morphCount; i++)
|
||||||
|
{
|
||||||
|
magic = nif->getInt();
|
||||||
|
type = nif->getInt();
|
||||||
|
std::vector<Ogre::Vector3> current;
|
||||||
|
std::vector<float> 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<Ogre::Vector3> 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
|
class NiKeyframeData : public Record
|
||||||
{
|
{
|
||||||
public:
|
std::string bonename;
|
||||||
|
//Rotations
|
||||||
|
std::vector<Ogre::Quaternion> quats;
|
||||||
|
std::vector<Ogre::Vector3> tbc;
|
||||||
|
std::vector<float> rottime;
|
||||||
|
float startTime;
|
||||||
|
float stopTime;
|
||||||
|
int rtype;
|
||||||
|
|
||||||
|
//Translations
|
||||||
|
std::vector<Ogre::Vector3> translist1;
|
||||||
|
std::vector<Ogre::Vector3> translist2;
|
||||||
|
std::vector<Ogre::Vector3> translist3;
|
||||||
|
std::vector<Ogre::Vector3> transtbc;
|
||||||
|
std::vector<float> transtime;
|
||||||
|
int ttype;
|
||||||
|
|
||||||
|
//Scalings
|
||||||
|
|
||||||
|
std::vector<float> scalefactor;
|
||||||
|
std::vector<float> scaletime;
|
||||||
|
std::vector<float> forwards;
|
||||||
|
std::vector<float> backwards;
|
||||||
|
std::vector<Ogre::Vector3> tbcscale;
|
||||||
|
int stype;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
void clone(NiKeyframeData c)
|
||||||
|
{
|
||||||
|
quats = c.getQuat();
|
||||||
|
tbc = c.getrTbc();
|
||||||
|
rottime = c.getrTime();
|
||||||
|
|
||||||
|
//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)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
// Rotations first
|
// Rotations first
|
||||||
int count = nif->getInt();
|
int count = nif->getInt();
|
||||||
|
//std::vector<Ogre::Quaternion> quat(count);
|
||||||
|
//std::vector<float> rottime(count);
|
||||||
if(count)
|
if(count)
|
||||||
{
|
{
|
||||||
int type = nif->getInt();
|
|
||||||
|
|
||||||
if(type == 1)
|
//TYPE1 LINEAR_KEY
|
||||||
nif->skip(count*4*5); // time + quaternion
|
//TYPE2 QUADRATIC_KEY
|
||||||
else if(type == 3)
|
//TYPE3 TBC_KEY
|
||||||
nif->skip(count*4*8); // rot1 + tension+bias+continuity
|
//TYPE4 XYZ_ROTATION_KEY
|
||||||
else if(type == 4)
|
//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;j<count;j++)
|
for(int j=0;j<count;j++)
|
||||||
{
|
{
|
||||||
|
@ -467,20 +657,69 @@ class NiKeyframeData : public Record
|
||||||
}
|
}
|
||||||
else nif->fail("Unknown rotation type in NiKeyframeData");
|
else nif->fail("Unknown rotation type in NiKeyframeData");
|
||||||
}
|
}
|
||||||
|
//first = false;
|
||||||
|
|
||||||
// Then translation
|
// Then translation
|
||||||
count = nif->getInt();
|
count = nif->getInt();
|
||||||
|
|
||||||
if(count)
|
if(count)
|
||||||
{
|
{
|
||||||
int type = nif->getInt();
|
ttype = nif->getInt();
|
||||||
|
|
||||||
if(type == 1)
|
//std::cout << "TransCount:" << count << " Type: " << type << "\n";
|
||||||
nif->getFloatLen(count*4); // time + translation
|
if(ttype == 1) {
|
||||||
else if(type == 2)
|
for (int i = 0; i < count; i++) {
|
||||||
nif->getFloatLen(count*10); // trans1 + forward + backward
|
float time = nif->getFloat();
|
||||||
else if(type == 3)
|
float x = nif->getFloat();
|
||||||
nif->getFloatLen(count*7); // trans1 + tension,bias,continuity
|
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");
|
else nif->fail("Unknown translation type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,16 +727,101 @@ class NiKeyframeData : public Record
|
||||||
count = nif->getInt();
|
count = nif->getInt();
|
||||||
if(count)
|
if(count)
|
||||||
{
|
{
|
||||||
int type = nif->getInt();
|
stype = nif->getInt();
|
||||||
|
|
||||||
int size = 0;
|
|
||||||
if(type == 1) size = 2; // time+scale
|
for(int i = 0; i < count; i++){
|
||||||
else if(type == 2) size = 4; // 1 + forward + backward (floats)
|
|
||||||
else if(type == 3) size = 5; // 1 + tbc
|
|
||||||
|
//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");
|
else nif->fail("Unknown scaling type");
|
||||||
nif->getFloatLen(count*size);
|
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<Ogre::Quaternion> getQuat(){
|
||||||
|
return quats;
|
||||||
|
}
|
||||||
|
std::vector<Ogre::Vector3> getrTbc(){
|
||||||
|
return tbc;
|
||||||
|
}
|
||||||
|
std::vector<float> getrTime(){
|
||||||
|
return rottime;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Ogre::Vector3> getTranslist1(){
|
||||||
|
return translist1;
|
||||||
|
}
|
||||||
|
std::vector<Ogre::Vector3> getTranslist2(){
|
||||||
|
return translist2;
|
||||||
|
}
|
||||||
|
std::vector<Ogre::Vector3> getTranslist3(){
|
||||||
|
return translist3;
|
||||||
|
}
|
||||||
|
std::vector<float> gettTime(){
|
||||||
|
return transtime;
|
||||||
|
}
|
||||||
|
std::vector<float> getScalefactor(){
|
||||||
|
return scalefactor;
|
||||||
|
}
|
||||||
|
std::vector<float> getForwards(){
|
||||||
|
return forwards;
|
||||||
|
}
|
||||||
|
std::vector<float> getBackwards(){
|
||||||
|
return backwards;
|
||||||
|
}
|
||||||
|
std::vector<Ogre::Vector3> getScaleTbc(){
|
||||||
|
return tbcscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<float> getsTime(){
|
||||||
|
return scaletime;
|
||||||
|
}
|
||||||
|
std::string getBonename(){ return bonename;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Namespace
|
} // Namespace
|
||||||
|
|
|
@ -93,6 +93,20 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NiTriShapeCopy
|
||||||
|
{
|
||||||
|
std::string sname;
|
||||||
|
std::vector<std::string> boneSequence;
|
||||||
|
Nif::NiSkinData::BoneTrafoCopy trafo;
|
||||||
|
//Ogre::Quaternion initialBoneRotation;
|
||||||
|
//Ogre::Vector3 initialBoneTranslation;
|
||||||
|
std::vector<Ogre::Vector3> vertices;
|
||||||
|
std::vector<Ogre::Vector3> normals;
|
||||||
|
std::vector<Nif::NiSkinData::BoneInfoCopy> boneinfo;
|
||||||
|
std::map<int, std::vector<Nif::NiSkinData::IndividualWeight> > vertsToWeights;
|
||||||
|
Nif::NiMorphData morph;
|
||||||
|
};
|
||||||
|
|
||||||
struct NiNode : Node
|
struct NiNode : Node
|
||||||
{
|
{
|
||||||
NodeList children;
|
NodeList children;
|
||||||
|
@ -133,6 +147,27 @@ struct NiTriShape : Node
|
||||||
data.read(nif);
|
data.read(nif);
|
||||||
skin.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
|
struct NiCamera : Node
|
||||||
|
@ -186,5 +221,7 @@ struct NiRotatingParticles : Node
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // Namespace
|
} // Namespace
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,25 +24,7 @@
|
||||||
//loadResource->handleNode->handleNiTriShape->createSubMesh
|
//loadResource->handleNode->handleNiTriShape->createSubMesh
|
||||||
|
|
||||||
#include "ogre_nif_loader.hpp"
|
#include "ogre_nif_loader.hpp"
|
||||||
#include <Ogre.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <libs/mangle/vfs/servers/ogre_vfs.hpp>
|
|
||||||
#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 <libs/platform/strings.h>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
// For warning messages
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
// float infinity
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
typedef unsigned char ubyte;
|
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,
|
void NIFLoader::createMaterial(const String &name,
|
||||||
const Vector &ambient,
|
const Vector &ambient,
|
||||||
const Vector &diffuse,
|
const Vector &diffuse,
|
||||||
|
@ -230,11 +218,24 @@ void NIFLoader::createMaterial(const String &name,
|
||||||
{
|
{
|
||||||
MaterialPtr material = MaterialManager::getSingleton().create(name, resourceGroup);
|
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
|
// This assigns the texture to this material. If the texture name is
|
||||||
// a file name, and this file exists (in a resource directory), it
|
// a file name, and this file exists (in a resource directory), it
|
||||||
// will automatically be loaded when needed. If not (such as for
|
// will automatically be loaded when needed. If not (such as for
|
||||||
// internal NIF textures that we might support later), we should
|
// internal NIF textures that we might support later), we should
|
||||||
// already have inserted a manual loader for the texture.
|
// already have inserted a manual loader for the texture.
|
||||||
|
|
||||||
|
|
||||||
if (!texName.empty())
|
if (!texName.empty())
|
||||||
{
|
{
|
||||||
Pass *pass = material->getTechnique(0)->getPass(0);
|
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->setSpecular(specular.array[0], specular.array[1], specular.array[2], alpha);
|
||||||
material->setSelfIllumination(emissive.array[0], emissive.array[1], emissive.array[2]);
|
material->setSelfIllumination(emissive.array[0], emissive.array[1], emissive.array[2]);
|
||||||
material->setShininess(glossiness);
|
material->setShininess(glossiness);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes a name and adds a unique part to it. This is just used to
|
// 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 =
|
HardwareVertexBufferSharedPtr vbuf =
|
||||||
HardwareBufferManager::getSingleton().createVertexBuffer(
|
HardwareBufferManager::getSingleton().createVertexBuffer(
|
||||||
VertexElement::getTypeSize(VET_FLOAT3),
|
VertexElement::getTypeSize(VET_FLOAT3),
|
||||||
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
|
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
|
||||||
vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, true);
|
|
||||||
|
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;
|
VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding;
|
||||||
bind->setBinding(nextBuf++, vbuf);
|
bind->setBinding(nextBuf++, vbuf);
|
||||||
|
|
||||||
// Vertex normals
|
|
||||||
if (data->normals.length)
|
if (data->normals.length)
|
||||||
{
|
{
|
||||||
decl->addElement(nextBuf, 0, VET_FLOAT3, VES_NORMAL);
|
decl->addElement(nextBuf, 0, VET_FLOAT3, VES_NORMAL);
|
||||||
vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
|
vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
|
||||||
VertexElement::getTypeSize(VET_FLOAT3),
|
VertexElement::getTypeSize(VET_FLOAT3),
|
||||||
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
|
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
|
||||||
vbuf->writeData(0, vbuf->getSizeInBytes(), data->normals.ptr, true);
|
|
||||||
|
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);
|
bind->setBinding(nextBuf++, vbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,30 +445,79 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std
|
||||||
bind->setBinding(nextBuf++, vbuf);
|
bind->setBinding(nextBuf++, vbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Texture UV coordinates
|
|
||||||
if (data->uvlist.length)
|
if (data->uvlist.length)
|
||||||
{
|
{
|
||||||
|
|
||||||
decl->addElement(nextBuf, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES);
|
decl->addElement(nextBuf, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES);
|
||||||
vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
|
vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
|
||||||
VertexElement::getTypeSize(VET_FLOAT2),
|
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);
|
bind->setBinding(nextBuf++, vbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Triangle faces
|
// Triangle faces - The total number of triangle points
|
||||||
int numFaces = data->triangles.length;
|
int numFaces = data->triangles.length;
|
||||||
|
|
||||||
if (numFaces)
|
if (numFaces)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
sub->indexData->indexCount = numFaces;
|
||||||
|
sub->indexData->indexStart = 0;
|
||||||
HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
|
HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
|
||||||
createIndexBuffer(HardwareIndexBuffer::IT_16BIT,
|
createIndexBuffer(HardwareIndexBuffer::IT_16BIT,
|
||||||
numFaces,
|
numFaces,
|
||||||
HardwareBuffer::HBU_STATIC_WRITE_ONLY);
|
HardwareBuffer::HBU_STATIC_WRITE_ONLY, true);
|
||||||
ibuf->writeData(0, ibuf->getSizeInBytes(), data->triangles.ptr, true);
|
|
||||||
|
if(flip && mFlipVertexWinding && sub->indexData->indexCount % 3 == 0){
|
||||||
|
|
||||||
sub->indexData->indexBuffer = ibuf;
|
sub->indexData->indexBuffer = ibuf;
|
||||||
sub->indexData->indexCount = numFaces;
|
|
||||||
sub->indexData->indexStart = 0;
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set material if one was given
|
// 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<std::string> boneSequence)
|
||||||
{
|
{
|
||||||
assert(shape != NULL);
|
assert(shape != NULL);
|
||||||
|
|
||||||
|
@ -636,11 +737,29 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
|
|
||||||
std::list<VertexBoneAssignment> vertexBoneAssignments;
|
std::list<VertexBoneAssignment> 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<Nif::NiGeomMorpherController*> (cont);
|
||||||
|
copy.morph = morph->data.get();
|
||||||
|
copy.morph.setStartTime(morph->timeStart);
|
||||||
|
copy.morph.setStopTime(morph->timeStop);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
//use niskindata for the position of vertices.
|
//use niskindata for the position of vertices.
|
||||||
if (!shape->skin.empty())
|
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<bool> vertexPosAbsolut(numVerts,false);
|
std::vector<bool> vertexPosAbsolut(numVerts,false);
|
||||||
|
std::vector<Ogre::Vector3> vertexPosOriginal(numVerts, Ogre::Vector3::ZERO);
|
||||||
|
std::vector<Ogre::Vector3> vertexNormalOriginal(numVerts, Ogre::Vector3::ZERO);
|
||||||
|
|
||||||
float *ptrNormals = (float*)data->normals.ptr;
|
float *ptrNormals = (float*)data->normals.ptr;
|
||||||
//the bone from skin->bones[boneIndex] is linked to skin->data->bones[boneIndex]
|
//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;
|
break;
|
||||||
}
|
}
|
||||||
//get the bone from bones array of skindata
|
//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());
|
bonePtr = mSkel->getBone(shape->skin->bones[boneIndex].name.toString());
|
||||||
|
|
||||||
// final_vector = old_vector + old_rotation*new_vector*old_scale
|
// final_vector = old_vector + old_rotation*new_vector*old_scale
|
||||||
|
|
||||||
|
|
||||||
|
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; i<it->weights.length; i++)
|
||||||
|
{
|
||||||
vecPos = bonePtr->_getDerivedPosition() +
|
vecPos = bonePtr->_getDerivedPosition() +
|
||||||
bonePtr->_getDerivedOrientation() * convertVector3(it->trafo->trans);
|
bonePtr->_getDerivedOrientation() * convertVector3(it->trafo->trans);
|
||||||
|
|
||||||
vecRot = bonePtr->_getDerivedOrientation() * convertRotation(it->trafo->rotation);
|
vecRot = bonePtr->_getDerivedOrientation() * convertRotation(it->trafo->rotation);
|
||||||
|
|
||||||
for (unsigned int i=0; i<it->weights.length; i++)
|
|
||||||
{
|
|
||||||
unsigned int verIndex = (it->weights.ptr + i)->vertex;
|
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<Nif::NiSkinData::IndividualWeight> 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?
|
//Check if the vertex is relativ, FIXME: Is there a better solution?
|
||||||
if (vertexPosAbsolut[verIndex] == false)
|
if (vertexPosAbsolut[verIndex] == false)
|
||||||
{
|
{
|
||||||
//apply transformation to the vertices
|
//apply transformation to the vertices
|
||||||
Vector3 absVertPos = vecPos + vecRot * Vector3(ptr + verIndex *3);
|
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 *
|
//convert it back to float *
|
||||||
for (int j=0; j<3; j++)
|
for (int j=0; j<3; j++)
|
||||||
(ptr + verIndex*3)[j] = absVertPos[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)
|
if (verIndex < data->normals.length)
|
||||||
{
|
{
|
||||||
Vector3 absNormalsPos = vecRot * Vector3(ptrNormals + verIndex *3);
|
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++)
|
for (int j=0; j<3; j++)
|
||||||
(ptrNormals + verIndex*3)[j] = absNormalsPos[j];
|
(ptrNormals + verIndex*3)[j] = absNormalsPos[j];
|
||||||
|
@ -701,27 +848,67 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
|
|
||||||
vertexPosAbsolut[verIndex] = true;
|
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;
|
VertexBoneAssignment vba;
|
||||||
vba.boneIndex = bonePtr->getHandle();
|
vba.boneIndex = bonePtr->getHandle();
|
||||||
vba.vertexIndex = verIndex;
|
vba.vertexIndex = verIndex;
|
||||||
vba.weight = (it->weights.ptr + i)->weight;
|
vba.weight = (it->weights.ptr + i)->weight;
|
||||||
|
|
||||||
|
|
||||||
vertexBoneAssignments.push_back(vba);
|
vertexBoneAssignments.push_back(vba);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
boneIndex++;
|
boneIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
|
copy.boneSequence = boneSequence;
|
||||||
// Rotate, scale and translate all the vertices,
|
// Rotate, scale and translate all the vertices,
|
||||||
const Matrix &rot = shape->trafo->rotation;
|
const Matrix &rot = shape->trafo->rotation;
|
||||||
const Vector &pos = shape->trafo->pos;
|
const Vector &pos = shape->trafo->pos;
|
||||||
float scale = shape->trafo->scale;
|
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; i<numVerts; i++)
|
for (int i=0; i<numVerts; i++)
|
||||||
{
|
{
|
||||||
vectorMulAdd(rot, pos, ptr, scale);
|
vectorMulAdd(rot, pos, ptr, scale);
|
||||||
|
Ogre::Vector3 absVertPos = Ogre::Vector3(*(ptr + 3 * i), *(ptr + 3 * i + 1), *(ptr + 3 * i + 2));
|
||||||
|
mBoundingBox.merge(absVertPos);
|
||||||
ptr += 3;
|
ptr += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,24 +922,58 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
|
||||||
ptr += 3;
|
ptr += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(!mSkel.isNull() ){
|
||||||
|
int boneIndex;
|
||||||
|
Ogre::Bone *parentBone = mSkel->getBone(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)
|
if (!hidden)
|
||||||
{
|
{
|
||||||
// Add this vertex set to the bounding box
|
// Add this vertex set to the bounding box
|
||||||
bounds.add(optr, numVerts);
|
bounds.add(optr, numVerts);
|
||||||
|
shapes.push_back(copy);
|
||||||
|
|
||||||
// Create the submesh
|
// Create the submesh
|
||||||
createOgreSubMesh(shape, material, vertexBoneAssignments);
|
createOgreSubMesh(shape, material, vertexBoneAssignments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NIFLoader::handleNode(Nif::Node *node, int flags,
|
void NIFLoader::calculateTransform()
|
||||||
const Transformation *trafo, BoundsFinder &bounds, Bone *parentBone)
|
{
|
||||||
|
// 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<std::string> boneSequence)
|
||||||
{
|
{
|
||||||
stack++;
|
|
||||||
//if( MWClass::isChest)
|
|
||||||
// cout << "u:" << node << "\n";
|
|
||||||
// Accumulate the flags from all the child nodes. This works for all
|
// Accumulate the flags from all the child nodes. This works for all
|
||||||
// the flags we currently use, at least.
|
// the flags we currently use, at least.
|
||||||
flags |= node->flags;
|
flags |= node->flags;
|
||||||
|
@ -780,6 +1001,58 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
|
||||||
// the engine, just skip this entire node.
|
// the engine, just skip this entire node.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e->recType == RC_NiTextKeyExtraData){
|
||||||
|
Nif::NiTextKeyExtraData* extra = dynamic_cast<Nif::NiTextKeyExtraData*> (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<Nif::NiTextKeyExtraData::TextKey>::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;
|
Bone *bone = 0;
|
||||||
|
@ -790,20 +1063,15 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
|
||||||
//FIXME: "Bip01" isn't every time the root bone
|
//FIXME: "Bip01" isn't every time the root bone
|
||||||
if (node->name == "Bip01" || node->name == "Root Bone") //root node, create a skeleton
|
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 )
|
mSkel = SkeletonManager::getSingleton().create(getSkeletonName(), resourceGroup, true);
|
||||||
{
|
|
||||||
//TODO: Get animation names
|
|
||||||
std::cout << node->name.toString() << " is root bone and has textkeyextradata!\n";
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mSkel.isNull()) //if there is a skeleton
|
if (!mSkel.isNull()) //if there is a skeleton
|
||||||
{
|
{
|
||||||
std::string name = node->name.toString();
|
std::string name = node->name.toString();
|
||||||
//if (isBeast && isChest)
|
boneSequence.push_back(name);
|
||||||
// std::cout << "NAME: " << name << "\n";
|
|
||||||
// Quick-n-dirty workaround for the fact that several
|
// Quick-n-dirty workaround for the fact that several
|
||||||
// bones may have the same name.
|
// bones may have the same name.
|
||||||
if(!mSkel->hasBone(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
|
// Apply the parent transformation to this node. We overwrite the
|
||||||
// existing data with the final transformation.
|
// existing data with the final transformation.
|
||||||
if (trafo)
|
if (trafo)
|
||||||
|
@ -846,201 +1114,97 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
|
||||||
{
|
{
|
||||||
NodeList &list = ((NiNode*)node)->children;
|
NodeList &list = ((NiNode*)node)->children;
|
||||||
int n = list.length();
|
int n = list.length();
|
||||||
int i = 0;
|
for (int i = 0; i<n; i++)
|
||||||
if(isHands){
|
|
||||||
//cout << "NumberOfNs: " << n << "Stack:" << stack << "\n";
|
|
||||||
//if(stack == 3)
|
|
||||||
//n=0;
|
|
||||||
}
|
|
||||||
for (; i<n; i++)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
if (list.has(i))
|
if (list.has(i))
|
||||||
handleNode(&list[i], flags, node->trafo, 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
|
std::string nodename = node->name.toString();
|
||||||
/*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 name = node->name.toString();
|
if (triname == "")
|
||||||
//if (isChest)
|
|
||||||
//std::cout << "NAME: " << name << "\n";
|
|
||||||
|
|
||||||
if(isChest && isBeast && skincounter == 0 && name.compare("Tri Chest") == 0){
|
|
||||||
//std::cout <<"BEASTCHEST1\n";
|
|
||||||
handleNiTriShape(dynamic_cast<NiTriShape*>(node), flags, bounds);
|
|
||||||
skincounter++;
|
|
||||||
}
|
|
||||||
else if(isChest && isBeast && skincounter == 1 && name.compare("Tri Tail") == 0){
|
|
||||||
//std::cout <<"BEASTCHEST2\n";
|
|
||||||
handleNiTriShape(dynamic_cast<NiTriShape*>(node), flags, bounds);
|
|
||||||
skincounter++;
|
|
||||||
}
|
|
||||||
else if(isChest && isBeast && skincounter == 2 && name.compare("Tri Left Foot") == 0){
|
|
||||||
//std::cout <<"BEASTCHEST3\n";
|
|
||||||
handleNiTriShape(dynamic_cast<NiTriShape*>(node), flags, bounds);
|
|
||||||
skincounter=1000;
|
|
||||||
}
|
|
||||||
else if (!isChest || !isBeast)
|
|
||||||
{
|
{
|
||||||
handleNiTriShape(dynamic_cast<NiTriShape*>(node), flags, bounds);
|
handleNiTriShape(dynamic_cast<NiTriShape*>(node), flags, bounds, original, boneSequence);
|
||||||
}
|
}
|
||||||
//if(isBeast && isChest)
|
else if(nodename.length() >= triname.length())
|
||||||
//cout << "Handling Shape, Stack " << stack <<"\n";
|
{
|
||||||
|
std::transform(nodename.begin(), nodename.end(), nodename.begin(), ::tolower);
|
||||||
|
if(triname == nodename.substr(0, triname.length()))
|
||||||
|
handleNiTriShape(dynamic_cast<NiTriShape*>(node), flags, bounds, original, boneSequence);
|
||||||
counter++;
|
|
||||||
}
|
}
|
||||||
/*if(isHands){
|
|
||||||
//cout << "Handling Shape, Stack " << stack <<"\n";
|
|
||||||
counter++;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stack--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NIFLoader::loadResource(Resource *resource)
|
void NIFLoader::loadResource(Resource *resource)
|
||||||
{
|
{
|
||||||
if(skincounter == 1000)
|
allanim.clear();
|
||||||
skincounter = 0;
|
shapes.clear();
|
||||||
stack = 0;
|
mBoundingBox.setNull();
|
||||||
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();
|
|
||||||
mesh = 0;
|
mesh = 0;
|
||||||
mSkel.setNull();
|
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
|
// Set up the VFS if it hasn't been done already
|
||||||
if (!vfs) vfs = new OgreVFS(resourceGroup);
|
if (!vfs) vfs = new OgreVFS(resourceGroup);
|
||||||
|
|
||||||
|
@ -1087,8 +1251,33 @@ void NIFLoader::loadResource(Resource *resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the node
|
// Handle the node
|
||||||
handleNode(node, 0, NULL, bounds, 0);
|
std::vector<std::string> boneSequence;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
handleNode(node, 0, NULL, bounds, 0, boneSequence);
|
||||||
|
if(addAnim)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < nif.numRecords(); i++)
|
||||||
|
{
|
||||||
|
Nif::NiKeyframeController *f = dynamic_cast<Nif::NiKeyframeController*>(nif.getRecord(i));
|
||||||
|
|
||||||
|
if(f != NULL)
|
||||||
|
{
|
||||||
|
hasAnim = true;
|
||||||
|
Nif::Node *o = dynamic_cast<Nif::Node*>(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.
|
// set the bounding value.
|
||||||
if (bounds.isValid())
|
if (bounds.isValid())
|
||||||
{
|
{
|
||||||
|
@ -1096,64 +1285,84 @@ void NIFLoader::loadResource(Resource *resource)
|
||||||
bounds.maxX(), bounds.maxY(), bounds.maxZ()));
|
bounds.maxX(), bounds.maxY(), bounds.maxZ()));
|
||||||
mesh->_setBoundingSphereRadius(bounds.getRadius());
|
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,
|
MeshPtr NIFLoader::load(const std::string &name,
|
||||||
const std::string &group)
|
const std::string &group)
|
||||||
{
|
{
|
||||||
|
|
||||||
MeshManager *m = MeshManager::getSingletonPtr();
|
MeshManager *m = MeshManager::getSingletonPtr();
|
||||||
// Check if the resource already exists
|
// Check if the resource already exists
|
||||||
ResourcePtr ptr = m->getByName(name, group);
|
ResourcePtr ptr = m->getByName(name, group);
|
||||||
MeshPtr resize;
|
MeshPtr themesh;
|
||||||
|
|
||||||
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";
|
|
||||||
|
|
||||||
if (!ptr.isNull()){
|
if (!ptr.isNull()){
|
||||||
|
themesh = MeshPtr(ptr);
|
||||||
//if(pieces > 1)
|
|
||||||
//cout << "It exists\n";
|
|
||||||
resize = MeshPtr(ptr);
|
|
||||||
//resize->load();
|
|
||||||
//resize->reload();
|
|
||||||
}
|
}
|
||||||
else // Nope, create a new one.
|
else // Nope, create a new one.
|
||||||
{
|
{
|
||||||
resize = MeshManager::getSingleton().createManual(name, group, NIFLoader::getSingletonPtr());
|
themesh = 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;
|
|
||||||
}
|
}
|
||||||
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<Nif::NiKeyframeData>* NIFLoader::getAnim(std::string lowername){
|
||||||
|
|
||||||
|
std::map<std::string,std::vector<Nif::NiKeyframeData>,ciLessBoost>::iterator iter = allanimmap.find(lowername);
|
||||||
|
std::vector<Nif::NiKeyframeData>* pass = 0;
|
||||||
|
if(iter != allanimmap.end())
|
||||||
|
pass = &(iter->second);
|
||||||
|
return pass;
|
||||||
|
|
||||||
|
}
|
||||||
|
std::vector<Nif::NiTriShapeCopy>* NIFLoader::getShapes(std::string lowername){
|
||||||
|
|
||||||
|
std::map<std::string,std::vector<Nif::NiTriShapeCopy>,ciLessBoost>::iterator iter = allshapesmap.find(lowername);
|
||||||
|
std::vector<Nif::NiTriShapeCopy>* pass = 0;
|
||||||
|
if(iter != allshapesmap.end())
|
||||||
|
pass = &(iter->second);
|
||||||
|
return pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, float>* NIFLoader::getTextIndices(std::string lowername){
|
||||||
|
std::map<std::string,std::map<std::string, float>, ciLessBoost>::iterator iter = alltextmappings.find(lowername);
|
||||||
|
std::map<std::string, float>* pass = 0;
|
||||||
|
if(iter != alltextmappings.end())
|
||||||
|
pass = &(iter->second);
|
||||||
|
return pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* More code currently not in use, from the old D source. This was
|
/* 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
|
used in the first attempt at loading NIF meshes, where each submesh
|
||||||
|
|
|
@ -28,10 +28,38 @@
|
||||||
#include <OgreMesh.h>
|
#include <OgreMesh.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <Ogre.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <libs/mangle/vfs/servers/ogre_vfs.hpp>
|
||||||
|
#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 <libs/platform/strings.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
// For warning messages
|
||||||
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
using namespace boost::algorithm;
|
||||||
|
|
||||||
|
|
||||||
class BoundsFinder;
|
class BoundsFinder;
|
||||||
|
|
||||||
|
struct ciLessBoost : std::binary_function<std::string, std::string, bool>
|
||||||
|
{
|
||||||
|
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
|
namespace Nif
|
||||||
{
|
{
|
||||||
class Node;
|
class Node;
|
||||||
|
@ -52,6 +80,7 @@ namespace Mangle
|
||||||
namespace NifOgre
|
namespace NifOgre
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
/** Manual resource loader for NIF meshes. This is the main class
|
/** Manual resource loader for NIF meshes. This is the main class
|
||||||
responsible for translating the internal NIF mesh structure into
|
responsible for translating the internal NIF mesh structure into
|
||||||
something Ogre can use. Later it will also handle the insertion of
|
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,
|
static Ogre::MeshPtr load(const std::string &name,
|
||||||
const std::string &group="General");
|
const std::string &group="General");
|
||||||
|
//void insertMeshInsideBase(Ogre::Mesh* mesh);
|
||||||
|
std::vector<Nif::NiKeyframeData>* getAnim(std::string name);
|
||||||
|
std::vector<Nif::NiTriShapeCopy>* getShapes(std::string name);
|
||||||
|
std::map<std::string, float>* getTextIndices(std::string name);
|
||||||
|
void addInMesh(Ogre::Mesh* input);
|
||||||
|
|
||||||
|
|
||||||
Ogre::Vector3 convertVector3(const Nif::Vector& vec);
|
Ogre::Vector3 convertVector3(const Nif::Vector& vec);
|
||||||
Ogre::Quaternion convertRotation(const Nif::Matrix& rot);
|
Ogre::Quaternion convertRotation(const Nif::Matrix& rot);
|
||||||
|
|
||||||
|
void setOutputAnimFiles(bool output);
|
||||||
|
void setVerbosePath(std::string path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NIFLoader() : resourceGroup("General") { skincounter = 0; resourceName = "";}
|
NIFLoader() : resourceName(""), resourceGroup("General"), flip(false), mNormaliseNormals(false),
|
||||||
|
mFlipVertexWinding(false), mOutputAnimFiles(false) {}
|
||||||
NIFLoader(NIFLoader& n) {}
|
NIFLoader(NIFLoader& n) {}
|
||||||
|
|
||||||
|
void calculateTransform();
|
||||||
|
|
||||||
|
|
||||||
void warn(std::string msg);
|
void warn(std::string msg);
|
||||||
void fail(std::string msg);
|
void fail(std::string msg);
|
||||||
|
|
||||||
void handleNode( Nif::Node *node, int flags,
|
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<std::string> boneSequence);
|
||||||
|
|
||||||
void handleNiTriShape(Nif::NiTriShape *shape, int flags, BoundsFinder &bounds);
|
void handleNiTriShape(Nif::NiTriShape *shape, int flags, BoundsFinder &bounds, Nif::Transformation original, std::vector<std::string> boneSequence);
|
||||||
|
|
||||||
void createOgreSubMesh(Nif::NiTriShape *shape, const Ogre::String &material, std::list<Ogre::VertexBoneAssignment> &vertexBoneAssignments);
|
void createOgreSubMesh(Nif::NiTriShape *shape, const Ogre::String &material, std::list<Ogre::VertexBoneAssignment> &vertexBoneAssignments);
|
||||||
|
|
||||||
|
@ -124,21 +164,34 @@ class NIFLoader : Ogre::ManualResourceLoader
|
||||||
// extension from .tga to .dds if the texture is missing.
|
// extension from .tga to .dds if the texture is missing.
|
||||||
Mangle::VFS::OgreVFS *vfs;
|
Mangle::VFS::OgreVFS *vfs;
|
||||||
|
|
||||||
|
std::string verbosePath;
|
||||||
std::string resourceName;
|
std::string resourceName;
|
||||||
std::string resourceGroup;
|
std::string resourceGroup;
|
||||||
int skincounter;
|
Ogre::Matrix4 mTransform;
|
||||||
bool isChest;
|
Ogre::AxisAlignedBox mBoundingBox;
|
||||||
bool isBeast;
|
bool flip;
|
||||||
bool isHands;
|
bool mNormaliseNormals;
|
||||||
bool isFeet;
|
bool mFlipVertexWinding;
|
||||||
int counter;
|
bool bNiTri;
|
||||||
int numbers;
|
bool mOutputAnimFiles;
|
||||||
int stack;
|
|
||||||
std::multimap<std::string,std::string> MaterialMap;
|
std::multimap<std::string,std::string> MaterialMap;
|
||||||
|
|
||||||
// pointer to the ogre mesh which is currently build
|
// pointer to the ogre mesh which is currently build
|
||||||
Ogre::Mesh *mesh;
|
Ogre::Mesh *mesh;
|
||||||
Ogre::SkeletonPtr mSkel;
|
Ogre::SkeletonPtr mSkel;
|
||||||
|
Ogre::Vector3 vector;
|
||||||
|
std::vector<Nif::NiTriShapeCopy> shapes;
|
||||||
|
std::string name;
|
||||||
|
std::string triname;
|
||||||
|
std::vector<Nif::NiKeyframeData> allanim;
|
||||||
|
std::map<std::string,float> textmappings;
|
||||||
|
std::map<std::string,std::map<std::string,float>,ciLessBoost> alltextmappings;
|
||||||
|
std::map<std::string,std::vector<Nif::NiKeyframeData>,ciLessBoost> allanimmap;
|
||||||
|
std::map<std::string,std::vector<Nif::NiTriShapeCopy>,ciLessBoost> allshapesmap;
|
||||||
|
std::vector<Ogre::Mesh*> addin;
|
||||||
|
std::vector<Nif::NiKeyframeData> mAnim;
|
||||||
|
std::vector<Nif::NiTriShapeCopy> mS;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue