Merge branch 'animation2'

actorid
Marc Zinnschlag 13 years ago
commit 0c2de2c00c

@ -16,7 +16,7 @@ set(GAME_HEADER
source_group(game FILES ${GAME} ${GAME_HEADER})
add_openmw_dir (mwrender
rendering_manager mwscene cellimp interior exterior sky player
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects renderinginterface
)
add_openmw_dir (mwinput
@ -36,6 +36,7 @@ add_openmw_dir (mwscript
locals scriptmanager compilercontext interpretercontext cellextensions miscextensions
guiextensions soundextensions skyextensions statsextensions containerextensions
aiextensions controlextensions extensions globalscripts ref dialogueextensions
animationextensions
)
add_openmw_dir (mwsound

@ -20,6 +20,7 @@
#include <components/esm/esm_reader.hpp>
#include <components/files/path.hpp>
#include <components/nifbullet/bullet_nif_loader.hpp>
#include <components/nifogre/ogre_nif_loader.hpp>
#include "mwinput/inputmanager.hpp"
@ -46,6 +47,7 @@
#include "mwmechanics/mechanicsmanager.hpp"
void OMW::Engine::executeLocalScripts()
{
MWWorld::LocalScripts& localScripts = mEnvironment.mWorld->getLocalScripts();
@ -69,6 +71,7 @@ void OMW::Engine::executeLocalScripts()
void OMW::Engine::updateFocusReport (float duration)
{
if ((mFocusTDiff += duration)>0.25)
{
mFocusTDiff = 0;
@ -81,8 +84,10 @@ void OMW::Engine::updateFocusReport (float duration)
{
MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle);
if (!ptr.isEmpty())
if (!ptr.isEmpty()){
name = MWWorld::Class::get (ptr).getName (ptr);
}
}
if (name!=mFocusName)
@ -97,6 +102,13 @@ void OMW::Engine::updateFocusReport (float duration)
}
}
void OMW::Engine::setAnimationVerbose(bool animverbose){
if(animverbose){
NifOgre::NIFLoader::getSingletonPtr()->setOutputAnimFiles(true);
NifOgre::NIFLoader::getSingletonPtr()->setVerbosePath(mCfgMgr.getLogPath().string());
}
}
bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
{
try
@ -135,6 +147,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
mEnvironment.mWorld->advanceTime (
mEnvironment.mFrameDuration*mEnvironment.mWorld->getTimeScaleFactor()/3600);
if (changed) // keep change flag for another frame, if cell changed happend in local script
mEnvironment.mWorld->markCellAsUnchanged();
@ -287,6 +300,7 @@ void OMW::Engine::setReportFocus (bool report)
void OMW::Engine::go()
{
mFocusTDiff = 0;
assert (!mEnvironment.mWorld);
assert (!mCellName.empty());
assert (!mMaster.empty());
@ -329,6 +343,7 @@ void OMW::Engine::go()
// Set up the GUI system
mGuiManager = new OEngine::GUI::MyGUIManager(mOgre->getWindow(), mOgre->getScene(), false,
mCfgMgr.getLogPath().string() + std::string("/"));
// Create window manager - this manages all the MW-specific GUI windows
MWScript::registerExtensions (mExtensions);

@ -158,6 +158,8 @@ namespace OMW
/// Font encoding
void setEncoding(const std::string& encoding);
void setAnimationVerbose(bool animverbose);
private:
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)
->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)
->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.setCompileAll(variables["script-all"].as<bool>());
engine.setReportFocus(variables["report-focus"].as<bool>());
engine.setAnimationVerbose(variables["anim-verbose"].as<bool>());
return true;
}

@ -1,5 +1,6 @@
#include "activator.hpp"
#include "../mwrender/objects.hpp"
#include <components/esm/loadacti.hpp>
@ -7,27 +8,39 @@
#include "../mwworld/ptr.hpp"
#include "../mwrender/cellimp.hpp"
namespace MWClass
{
void Activator::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData> *ref =
ptr.get<ESM::Activator>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
}
}
void Activator::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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
{
ESMS::LiveCellRef<ESM::Activator, MWWorld::RefData> *ref =

@ -9,10 +9,11 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -8,29 +8,41 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp"
namespace MWClass
{
void Apparatus::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Apparatus::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =
ptr.get<ESM::Apparatus>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
}
}
void Apparatus::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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
{
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =

@ -2,6 +2,7 @@
#define GAME_MWCLASS_APPARATUS_H
#include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass
{
@ -9,10 +10,11 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -8,29 +8,40 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp"
namespace MWClass
{
void Armor::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Armor::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
ptr.get<ESM::Armor>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
}
}
void Armor::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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
{
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =

@ -2,6 +2,7 @@
#define GAME_MWCLASS_ARMOR_H
#include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass
{
@ -9,10 +10,11 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -8,29 +8,41 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp"
namespace MWClass
{
void Book::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Book::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
ptr.get<ESM::Book>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
}
}
void Book::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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
{
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =

@ -2,6 +2,7 @@
#define GAME_MWCLASS_BOOK_H
#include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass
{
@ -9,10 +10,11 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -8,29 +8,41 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp"
namespace MWClass
{
void Clothing::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Clothing::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
ptr.get<ESM::Clothing>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
}
}
void Clothing::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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
{
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =

@ -2,6 +2,7 @@
#define GAME_MWCLASS_CLOTHING_H
#include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass
{
@ -9,10 +10,11 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -7,25 +7,36 @@
#include "../mwworld/ptr.hpp"
#include "../mwrender/cellimp.hpp"
namespace MWClass
{
void Container::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Container::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref =
ptr.get<ESM::Container>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
}
}
void Container::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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

@ -2,6 +2,7 @@
#define GAME_MWCLASS_CONTAINER_H
#include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass
{
@ -9,10 +10,11 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -9,7 +9,6 @@
#include "../mwworld/actiontalk.hpp"
#include "../mwworld/environment.hpp"
#include "../mwrender/cellimp.hpp"
#include "../mwmechanics/mechanicsmanager.hpp"
@ -23,21 +22,34 @@ namespace MWClass
return ref->base->mId;
}
void Creature::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =
/*ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =
ptr.get<ESM::Creature>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh("meshes\\" + model);
cellRender.insertActorPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
{*/
MWRender::Actors& actors = renderingInterface.getActors();
actors.insertCreature(ptr);
}
void Creature::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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

@ -2,6 +2,9 @@
#define GAME_MWCLASS_CREATURE_H
#include "../mwworld/class.hpp"
#include "../mwrender/renderinginterface.hpp"
#include "../mwrender/actors.hpp"
namespace MWClass
{
@ -12,10 +15,11 @@ namespace MWClass
virtual std::string getId (const MWWorld::Ptr& ptr) const;
///< Return ID of \a ptr
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
///< Enable reference; only does the non-rendering part

@ -12,29 +12,42 @@
#include "../mwworld/environment.hpp"
#include "../mwworld/world.hpp"
#include "../mwrender/cellimp.hpp"
#include "../mwrender/objects.hpp"
#include <iostream>
namespace MWClass
{
void Door::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Door::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
ptr.get<ESM::Door>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
}
}
void Door::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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
{
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =

@ -2,6 +2,7 @@
#define GAME_MWCLASS_DOOR_H
#include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass
{
@ -9,10 +10,11 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -8,29 +8,42 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp"
namespace MWClass
{
void Ingredient::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Ingredient::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =
ptr.get<ESM::Ingredient>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
}
}
void Ingredient::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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
{
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =

@ -2,6 +2,7 @@
#define GAME_MWCLASS_INGREDIENT_H
#include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass
{
@ -9,10 +10,11 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -10,39 +10,46 @@
#include "../mwworld/nullaction.hpp"
#include "../mwworld/environment.hpp"
#include "../mwrender/cellimp.hpp"
#include "../mwsound/soundmanager.hpp"
#include "containerutil.hpp"
namespace MWClass
{
void Light::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Light::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
ptr.get<ESM::Light>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
// Extract the color and convert to floating point
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
const int color = ref->base->data.color;
const float r = ((color >> 0) & 0xFF) / 255.0f;
const float g = ((color >> 8) & 0xFF) / 255.0f;
const float r = ((color >> 0) & 0xFF) / 255.0f;
const float g = ((color >> 8) & 0xFF) / 255.0f;
const float b = ((color >> 16) & 0xFF) / 255.0f;
const float radius = float (ref->base->data.radius);
cellRender.insertLight (r, g, b, radius);
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

@ -2,6 +2,7 @@
#define GAME_MWCLASS_LIGHT_H
#include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass
{
@ -9,10 +10,11 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
///< Enable reference; only does the non-rendering part
/// \attention This is not the same as the script instruction with the same name. References

@ -8,29 +8,41 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp"
namespace MWClass
{
void Lockpick::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Lockpick::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =
ptr.get<ESM::Tool>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
}
}
void Lockpick::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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
{
ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =

@ -2,6 +2,7 @@
#define GAME_MWCLASS_LOCKPICK_H
#include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass
{
@ -9,10 +10,11 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -8,27 +8,38 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp"
namespace MWClass
{
void Miscellaneous::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
ptr.get<ESM::Miscellaneous>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
}
}
void Miscellaneous::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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

@ -2,6 +2,7 @@
#define GAME_MWCLASS_MISC_H
#include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass
{
@ -9,10 +10,11 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -11,8 +11,6 @@
#include "../mwworld/environment.hpp"
#include "../mwworld/world.hpp"
#include "../mwrender/cellimp.hpp"
#include "../mwmechanics/mechanicsmanager.hpp"
#include <OgreSceneNode.h>
@ -32,229 +30,31 @@ namespace MWClass
return ref->base->mId;
}
void Npc::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
//Ogre::SceneNode *chest;
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
ptr.get<ESM::NPC>();
//Store scenenodes by npc's name + bodypart [0] , npc's name + bodypart [1]
//Ex. Fargothchest , Fargothneck
assert (ref->base != NULL);
std::string hairID = ref->base->hair;
std::string headID = ref->base->head;
// very ugly workaround to stop OGRE from chocking on non-unique scene node handles
static int uniqueId = 0;
std::ostringstream stream;
stream << "npc$" << uniqueId++;
std::string npcName = stream.str(); // ref->base->name;
//std::cout << "NPC: " << npcName << "\n";
//get the part of the bodypart id which describes the race and the gender
std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4);
std::string headModel = "meshes\\" +
environment.mWorld->getStore().bodyParts.find(headID)->model;
std::string hairModel = "meshes\\" +
environment.mWorld->getStore().bodyParts.find(hairID)->model;
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
//TODO: define consts for each bodypart e.g. chest, foot, wrist... and put the parts in the
// right place
const ESM::BodyPart *bodyPart =
environment.mWorld->getStore().bodyParts.search (bodyRaceID + "chest");
//bodyPart->model->
Ogre::Vector3 pos = Ogre::Vector3( 20, 20, 20);
Ogre::Vector3 axis = Ogre::Vector3( 0, 0, 1);
Ogre::Radian angle = Ogre::Radian(0);
std::string addresses[6] = {"", "", "", "","", ""};
std::string addresses2[6] = {"", "", "", "", "", ""};
std::string upperleft[5] = {"", "", "", "", ""};
std::string upperright[5] = {"", "", "", "", ""};
std::string neckandup[5] = {"", "", "","",""};
int numbers = 0;
int uppernumbers = 0;
int neckNumbers = 0;
if (bodyPart){
cellRender.insertMesh("meshes\\" + bodyPart->model, pos, axis, angle, npcName + "chest", addresses, numbers, true); //2 0
addresses2[numbers] = npcName + "chest";
addresses[numbers++] = npcName + "chest";
upperleft[uppernumbers] = npcName + "chest";
upperright[uppernumbers++] = npcName + "chest";
neckandup[neckNumbers++] = npcName + "chest";
}
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
renderingInterface.getActors().insertNPC(ptr);
}
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);
}
void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
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);
}
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
ptr.get<ESM::NPC>();
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";
}
assert (ref->base != NULL);
std::string headID = ref->base->head;
std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4);
bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_";
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);
}
std::string smodel = "meshes\\base_anim.nif";
if(beast)
smodel = "meshes\\base_animkna.nif";
physics.insertActorPhysics(ptr, smodel);
//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

@ -3,6 +3,7 @@
#include "../mwworld/class.hpp"
namespace MWClass
{
class Npc : public MWWorld::Class
@ -12,10 +13,11 @@ namespace MWClass
virtual std::string getId (const MWWorld::Ptr& ptr) const;
///< Return ID of \a ptr
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual void enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const;
///< Enable reference; only does the non-rendering part

@ -8,29 +8,41 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp"
namespace MWClass
{
void Potion::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Potion::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =
ptr.get<ESM::Potion>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
}
}
void Potion::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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
{
ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =

@ -2,6 +2,7 @@
#define GAME_MWCLASS_POTION_H
#include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass
{
@ -9,10 +10,11 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -8,29 +8,42 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass
{
void Probe::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Probe::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =
ptr.get<ESM::Probe>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
}
}
void Probe::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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
{
ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =
@ -38,7 +51,6 @@ namespace MWClass
return ref->base->name;
}
boost::shared_ptr<MWWorld::Action> Probe::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
{

@ -3,16 +3,18 @@
#include "../mwworld/class.hpp"
namespace MWClass
{
class Probe : public MWWorld::Class
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -8,27 +8,38 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp"
namespace MWClass
{
void Repair::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Repair::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref =
ptr.get<ESM::Repair>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
}
}
void Repair::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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

@ -2,6 +2,7 @@
#define GAME_MWCLASS_REPAIR_H
#include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass
{
@ -9,10 +10,11 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -5,27 +5,39 @@
#include "../mwworld/ptr.hpp"
#include "../mwrender/cellimp.hpp"
namespace MWClass
{
void Static::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Static::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Static, MWWorld::RefData> *ref =
ptr.get<ESM::Static>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData, true);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
}
}
void Static::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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
{
return "";

@ -2,6 +2,7 @@
#define GAME_MWCLASS_STATIC_H
#include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass
{
@ -9,10 +10,11 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -8,29 +8,41 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwrender/cellimp.hpp"
#include "containerutil.hpp"
namespace MWClass
{
void Weapon::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Weapon::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
ptr.get<ESM::Weapon>();
assert (ref->base != NULL);
const std::string &model = ref->base->model;
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertObjectPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model);
}
}
void Weapon::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
{
ESMS::LiveCellRef<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
{
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =

@ -2,6 +2,7 @@
#define GAME_MWCLASS_WEAPON_H
#include "../mwworld/class.hpp"
#include "../mwrender/objects.hpp"
namespace MWClass
{
@ -9,10 +10,11 @@ namespace MWClass
{
public:
virtual void insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
///< Add reference into a cell for rendering
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -250,6 +250,7 @@ namespace MWMechanics
while (iter!=mActors.end())
if (iter->getCell()==cellStore)
{
//std::cout << "Erasing an actor";
mActors.erase (iter++);
}
else

@ -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);
}
}

@ -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

@ -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 = &copy.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 = &copy.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++;
}
}
}
}

@ -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

@ -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());
}
}
}

@ -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

@ -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;
}

@ -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

@ -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++;
}
}
}
}

@ -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

@ -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();
}
}

@ -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
{
Player::Player (Ogre::Camera *camera, const std::string& handle)
: mCamera (camera), mHandle (handle)
Player::Player (Ogre::Camera *camera, Ogre::SceneNode* node)
: mCamera (camera), mNode (node)
{}
}

@ -2,6 +2,7 @@
#define GAME_MWRENDER_PLAYER_H
#include <iostream>
#include <Ogre.h>
namespace Ogre
{
@ -14,15 +15,16 @@ namespace MWRender
class Player
{
Ogre::Camera *mCamera;
std::string mHandle;
Ogre::SceneNode* mNode;
public:
Player (Ogre::Camera *camera, const std::string& handle);
Player (Ogre::Camera *camera, Ogre::SceneNode* mNode);
Ogre::Camera *getCamera() { return mCamera; }
std::string getHandle() const { return mHandle; }
std::string getHandle() const { return mNode->getName(); }
Ogre::SceneNode* getNode() {return mNode;}
};
}

@ -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

@ -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

@ -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
}
}

@ -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

@ -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>);
}
}
}

@ -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 0x20004: Lock
op 0x20005: Lock, explicit reference
opcodes 0x20006-0x3ffff unused
op 0x20006: PlayAnim
op 0x20007: PlayAnim, explicit reference
op 0x20008: LoopAnim
op 0x20009: LoopAnim, explicit reference
opcodes 0x2000a-0x3ffff unused
Segment 4:
(not implemented yet)
@ -109,4 +113,6 @@ op 0x2000134: SetJournalIndex
op 0x2000135: GetJournalIndex
op 0x2000136: GetPCCell
op 0x2000137: GetButtonPressed
opcodes 0x2000138-0x3ffffff unused
op 0x2000138: SkipAnim
op 0x2000139: SkipAnim, expplicit reference
opcodes 0x200013a-0x3ffffff unused

@ -14,6 +14,7 @@
#include "aiextensions.hpp"
#include "controlextensions.hpp"
#include "dialogueextensions.hpp"
#include "animationextensions.hpp"
namespace MWScript
{
@ -29,6 +30,7 @@ namespace MWScript
Ai::registerExtensions (extensions);
Control::registerExtensions (extensions);
Dialogue::registerExtensions (extensions);
Animation::registerExtensions (extensions);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -44,5 +46,6 @@ namespace MWScript
Ai::installOpcodes (interpreter);
Control::installOpcodes (interpreter);
Dialogue::installOpcodes (interpreter);
Animation::installOpcodes (interpreter);
}
}

@ -16,12 +16,12 @@ namespace MWWorld
/// List all (Ogre-)handles.
struct ListHandles
{
std::vector<std::string> mHandles;
std::vector<Ogre::SceneNode*> mHandles;
bool operator() (ESM::CellRef& ref, RefData& data)
{
std::string handle = data.getHandle();
if (!handle.empty())
Ogre::SceneNode* handle = data.getBaseNode();
if (handle)
mHandles.push_back (handle);
return true;
}

@ -21,10 +21,12 @@ namespace MWWorld
throw std::runtime_error ("class does not support ID retrieval");
}
void Class::insertObj (const Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const
void Class::insertObjectRendering (const Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
}
void Class::insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const{
}
void Class::enable (const Ptr& ptr, MWWorld::Environment& environment) const

@ -9,6 +9,8 @@
#include "action.hpp"
#include "containerstore.hpp"
#include "refdata.hpp"
#include "../mwrender/renderinginterface.hpp"
#include "physicssystem.hpp"
namespace Ogre
{
@ -59,8 +61,10 @@ namespace MWWorld
///< Return ID of \a ptr or throw an exception, if class does not support ID retrieval
/// (default implementation: throw an exception)
virtual void insertObj (const Ptr& ptr, MWRender::CellRenderImp& cellRender,
MWWorld::Environment& environment) const;
virtual void insertObjectRendering (const Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
virtual void insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const;
///< Add reference into a cell for rendering (default implementation: don't render anything).
virtual void enable (const Ptr& ptr, MWWorld::Environment& environment) const;

@ -1,3 +1,5 @@
#include <stdexcept>
#include "physicssystem.hpp"
#include "../mwworld/ptr.hpp"
#include "../mwworld/world.hpp" // FIXME
@ -10,6 +12,7 @@
#include "OgreTextureManager.h"
using namespace Ogre;
namespace MWWorld
{
@ -23,6 +26,22 @@ namespace MWWorld
{
}
std::pair<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,
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)
{
if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle))
{
// TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow
// start positions others than 0, 0, 0
act->setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w));
}
}
void PhysicsSystem::scaleObject (const std::string& handle, float scale)
@ -137,28 +162,43 @@ namespace MWWorld
{
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++)
{
OEngine::Physic::PhysicActor* act = it->second;
bool cmode = act->getCollisionMode();
if(cmode)
{
act->enableCollisions(false);
act->setGravity(0.);
act->setVerticalVelocity(0);
mFreeFly = true;
return false;
}
else
if (it->first=="player")
{
mFreeFly = false;
act->enableCollisions(true);
act->setGravity(4.);
act->setVerticalVelocity(0);
return true;
OEngine::Physic::PhysicActor* act = it->second;
bool cmode = act->getCollisionMode();
if(cmode)
{
act->enableCollisions(false);
act->setGravity(0.);
act->setVerticalVelocity(0);
mFreeFly = true;
return false;
}
else
{
mFreeFly = false;
act->enableCollisions(true);
act->setGravity(4.);
act->setVerticalVelocity(0);
return true;
}
}
}
return false; // This should never happen, but it shall not bother us now, since
// this part of the code needs a rewrite anyway.
throw std::logic_error ("can't find player");
}
void PhysicsSystem::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string model){
Ogre::SceneNode* node = ptr.getRefData().getBaseNode();
addObject (node->getName(), model, node->getOrientation(),
node->getScale().x, node->getPosition());
}
void PhysicsSystem::insertActorPhysics(const MWWorld::Ptr& ptr, const std::string model){
Ogre::SceneNode* node = ptr.getRefData().getBaseNode();
// std::cout << "Adding node with name" << node->getName();
addActor (node->getName(), model, node->getPosition());
}
}

@ -4,6 +4,7 @@
#include <vector>
#include <openengine/ogre/renderer.hpp>
#include <openengine/bullet/physic.hpp>
#include "ptr.hpp"
namespace MWWorld
{
@ -32,6 +33,11 @@ namespace MWWorld
void scaleObject (const std::string& handle, float scale);
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:
OEngine::Render::OgreRenderer &mRender;

@ -22,7 +22,8 @@ namespace MWWorld
playerPos[0] = playerPos[1] = playerPos[2] = 0;
std::cout << renderer->getHandle();
mPlayer.mData.setHandle (renderer->getHandle());
mPlayer.mData.setBaseNode(renderer->getNode());
/// \todo Do not make a copy of classes defined in esm/p records.
mClass = new ESM::Class (*world.getStore().classes.find (player->cls));
}
@ -34,7 +35,7 @@ namespace MWWorld
void Player::setPos(float x, float y, float z)
{
/// \todo This fcuntion should be removed during the mwrender-refactoring.
/// \todo This fcuntion should be removed during the mwrender-refactoring.
mWorld.moveObject (getPlayer(), x, y, z);
}

@ -12,6 +12,7 @@
#include "../mwmechanics/movement.hpp"
#include "containerstore.hpp"
#include <Ogre.h>
namespace ESM
{
@ -22,7 +23,8 @@ namespace MWWorld
{
class RefData
{
std::string mHandle;
Ogre::SceneNode* mBaseNode;
MWScript::Locals mLocals; // if we find the overhead of heaving a locals
// object in the refdata of refs without a script,
@ -43,16 +45,24 @@ namespace MWWorld
ESM::Position mPosition;
public:
/// @param cr Used to copy constant data such as position into this class where it can
/// be altered without effecting the original data. This makes it possible
/// to reset the position as the orignal data is still held in the CellRef
RefData(const ESMS::CellRef& cr) : mHasLocals (false), mEnabled (true),
RefData(const ESMS::CellRef& cr) : mBaseNode(0), mHasLocals (false), mEnabled (true),
mCount (1), mPosition(cr.pos) {}
std::string getHandle()
{
return mHandle;
return mBaseNode->getName();
}
Ogre::SceneNode* getBaseNode(){
return mBaseNode;
}
void setBaseNode(Ogre::SceneNode* base){
mBaseNode = base;
}
int getCount() const
@ -69,10 +79,6 @@ namespace MWWorld
}
}
void setHandle (const std::string& handle)
{
mHandle = handle;
}
void setCount (int count)
{

@ -1,8 +1,6 @@
#include "scene.hpp"
#include "world.hpp"
#include "../mwrender/interior.hpp"
#include "../mwrender/exterior.hpp"
#include "../mwmechanics/mechanicsmanager.hpp"
@ -18,11 +16,13 @@
namespace {
template<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())
{
//const MWWorld::Class& class_ = MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.list.begin(), &cell));
const MWWorld::Class& class_ =
MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.list.begin(), &cell));
for (typename T::List::iterator it = cellRefList.list.begin();
it != cellRefList.list.end(); it++)
@ -30,11 +30,18 @@ void insertCellRefList (T& cellRefList, ESMS::CellStore<MWWorld::RefData> &cell)
if (it->mData.getCount() || it->mData.isEnabled())
{
MWWorld::Ptr ptr (&*it, &cell);
/* TODO: call
* RenderingManager.insertObject
* class_.insertObjectPhysic
* class_.insertObjectMechanics
*/
try
{
rendering.addObject(ptr);
class_.insertObject(ptr, physics, environment);
class_.enable (ptr, environment);
}
catch (const std::exception& e)
{
std::string error ("error during rendering: ");
std::cerr << error + e.what() << std::endl;
}
}
}
}
@ -45,40 +52,57 @@ void insertCellRefList (T& cellRefList, ESMS::CellStore<MWWorld::RefData> &cell)
namespace MWWorld
{
void Scene::unloadCell (CellRenderCollection::iterator iter)
void Scene::advanceTime(){
mRendering.addTime();
}
void Scene::unloadCell (CellStoreCollection::iterator iter)
{
std::cout << "Unloading cell\n";
ListHandles functor;
iter->first->forEach<ListHandles>(functor);
{ // silence annoying g++ warning
for (std::vector<std::string>::const_iterator iter (functor.mHandles.begin());
iter!=functor.mHandles.end(); ++iter)
mPhysics->removeObject (*iter);
}
MWWorld::Ptr::CellStore* active = *iter;
active->forEach<ListHandles>(functor);
{
mWorld->getLocalScripts().clearCell (iter->first);
mEnvironment.mMechanicsManager->dropActors (iter->first);
mEnvironment.mSoundManager->stopSound (iter->first);
delete iter->second;
mActiveCells.erase (iter);
// 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);
}
void Scene::loadCell (Ptr::CellStore *cell, MWRender::CellRender *render)
void Scene::loadCell (Ptr::CellStore *cell)
{
// register local scripts
mWorld->getLocalScripts().addCell (cell);
// This connects the cell data with the rendering scene.
std::pair<CellRenderCollection::iterator, bool> result =
mActiveCells.insert (std::make_pair (cell, render));
if (result.second)
{
// Load the cell and insert it into the renderer
result.first->second->show();
std::pair<CellStoreCollection::iterator, bool> result =
mActiveCells.insert(cell);
if(result.second){
insertCell(*cell, mEnvironment);
mRendering.cellAdded (cell);
mRendering.configureAmbient(*cell);
}
}
void Scene::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position,
@ -98,14 +122,14 @@ namespace MWWorld
// remove active
mEnvironment.mMechanicsManager->removeActor (mWorld->getPlayer().getPlayer());
CellRenderCollection::iterator active = mActiveCells.begin();
CellStoreCollection::iterator active = mActiveCells.begin();
while (active!=mActiveCells.end())
{
if (!(active->first->cell->data.flags & ESM::Cell::Interior))
if (!((*active)->cell->data.flags & ESM::Cell::Interior))
{
if (std::abs (X-active->first->cell->data.gridX)<=1 &&
std::abs (Y-active->first->cell->data.gridY)<=1)
if (std::abs (X-(*active)->cell->data.gridX)<=1 &&
std::abs (Y-(*active)->cell->data.gridY)<=1)
{
// keep cells within the new 3x3 grid
++active;
@ -120,14 +144,14 @@ namespace MWWorld
for (int x=X-1; x<=X+1; ++x)
for (int y=Y-1; y<=Y+1; ++y)
{
CellRenderCollection::iterator iter = mActiveCells.begin();
CellStoreCollection::iterator iter = mActiveCells.begin();
while (iter!=mActiveCells.end())
{
assert (!(iter->first->cell->data.flags & ESM::Cell::Interior));
assert (!((*iter)->cell->data.flags & ESM::Cell::Interior));
if (x==iter->first->cell->data.gridX &&
y==iter->first->cell->data.gridY)
if (x==(*iter)->cell->data.gridX &&
y==(*iter)->cell->data.gridY)
break;
++iter;
@ -137,19 +161,19 @@ namespace MWWorld
{
Ptr::CellStore *cell = mWorld->getExterior(x, y);
loadCell (cell, new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene, mPhysics));
loadCell (cell);
}
}
// find current cell
CellRenderCollection::iterator iter = mActiveCells.begin();
CellStoreCollection::iterator iter = mActiveCells.begin();
while (iter!=mActiveCells.end())
{
assert (!(iter->first->cell->data.flags & ESM::Cell::Interior));
assert (!((*iter)->cell->data.flags & ESM::Cell::Interior));
if (X==iter->first->cell->data.gridX &&
Y==iter->first->cell->data.gridY)
if (X==(*iter)->cell->data.gridX &&
Y==(*iter)->cell->data.gridY)
break;
++iter;
@ -157,7 +181,7 @@ namespace MWWorld
assert (iter!=mActiveCells.end());
mCurrentCell = iter->first;
mCurrentCell = *iter;
// adjust player
playerCellChange (mWorld->getExterior(X, Y), position, adjustPlayerPos);
@ -168,17 +192,15 @@ namespace MWWorld
mCellChanged = true;
}
Scene::Scene (Environment& environment, World *world, MWRender::MWScene& scene, PhysicsSystem *physics)
: mScene (scene), mCurrentCell (0),
mCellChanged (false), mEnvironment (environment), mWorld(world), mPhysics(physics)
//We need the ogre renderer and a scene node.
Scene::Scene (Environment& environment, World *world, MWRender::RenderingManager& rendering, PhysicsSystem *physics)
: mCurrentCell (0), mCellChanged (false), mEnvironment (environment), mWorld(world),
mPhysics(physics), mRendering(rendering)
{
}
Scene::~Scene()
{
for (CellRenderCollection::iterator iter (mActiveCells.begin());
iter!=mActiveCells.end(); ++iter)
delete iter->second;
}
bool Scene::hasCellChanged() const
@ -186,15 +208,16 @@ namespace MWWorld
return mCellChanged;
}
const Scene::CellRenderCollection& Scene::getActiveCells() const
const Scene::CellStoreCollection& Scene::getActiveCells() const
{
return mActiveCells;
}
void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position)
{
std::cout << "Changing to interior\n";
// remove active
CellRenderCollection::iterator active = mActiveCells.begin();
CellStoreCollection::iterator active = mActiveCells.begin();
while (active!=mActiveCells.end())
{
@ -205,7 +228,7 @@ namespace MWWorld
std::cout << "cellName:" << cellName << std::endl;
Ptr::CellStore *cell = mWorld->getInterior(cellName);
loadCell (cell, new MWRender::InteriorCellRender (*cell, mEnvironment, mScene, mPhysics));
loadCell (cell);
// adjust player
mCurrentCell = cell;
@ -215,7 +238,6 @@ namespace MWWorld
mWorld->adjustSky();
mCellChanged = true;
//currentRegion->name = "";
}
void Scene::changeToExteriorCell (const ESM::Position& position)
@ -238,36 +260,31 @@ namespace MWWorld
mCellChanged = false;
}
/*#include <cassert>
#include <iostream>
#include <exception>
#include "../mwworld/class.hpp"
#include "../mwworld/ptr.hpp"*/
void Scene::insertCell(ESMS::CellStore<MWWorld::RefData> &cell)
void Scene::insertCell(ESMS::CellStore<MWWorld::RefData> &cell,
MWWorld::Environment& environment)
{
// Loop through all references in the cell
insertCellRefList (cell.activators, cell);
insertCellRefList (cell.potions, cell);
insertCellRefList (cell.appas, cell);
insertCellRefList (cell.armors, cell);
insertCellRefList (cell.books, cell);
insertCellRefList (cell.clothes, cell);
insertCellRefList (cell.containers, cell);
insertCellRefList (cell.creatures, cell);
insertCellRefList (cell.doors, cell);
insertCellRefList (cell.ingreds, cell);
insertCellRefList (cell.creatureLists, cell);
insertCellRefList (cell.itemLists, cell);
insertCellRefList (cell.lights, cell);
insertCellRefList (cell.lockpicks, cell);
insertCellRefList (cell.miscItems, cell);
insertCellRefList (cell.npcs, cell);
insertCellRefList (cell.probes, cell);
insertCellRefList (cell.repairs, cell);
insertCellRefList (cell.statics, cell);
insertCellRefList (cell.weapons, cell);
insertCellRefList(mRendering, environment, cell.activators, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.potions, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.appas, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.armors, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.books, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.clothes, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.containers, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.creatures, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.doors, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.ingreds, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.creatureLists, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.itemLists, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.lights, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.lockpicks, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.miscItems, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.npcs, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.probes, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.repairs, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.statics, cell, *mPhysics);
insertCellRefList(mRendering, environment, cell.weapons, cell, *mPhysics);
}
}

@ -6,17 +6,18 @@
#include <boost/filesystem.hpp>
#include <openengine/bullet/physic.hpp>
#include <components/esm_store/cell_store.hpp>
#include "../mwrender/mwscene.hpp"
#include "physicssystem.hpp"
#include "../mwrender/renderingmanager.hpp"
#include "../mwrender/renderinginterface.hpp"
#include "physicssystem.hpp"
#include "refdata.hpp"
#include "ptr.hpp"
#include "globals.hpp"
#include <openengine/bullet/physic.hpp>
namespace Ogre
{
class Vector3;
@ -53,29 +54,32 @@ namespace MWWorld
public:
typedef std::map<Ptr::CellStore *, MWRender::CellRender *> CellRenderCollection;
typedef std::set<Ptr::CellStore *> CellStoreCollection;
private:
MWRender::MWScene& mScene;
Ptr::CellStore *mCurrentCell; // the cell, the player is in
CellRenderCollection mActiveCells;
//OEngine::Render::OgreRenderer& mRenderer;
Ptr::CellStore* mCurrentCell; // the cell, the player is in
CellStoreCollection mActiveCells;
bool mCellChanged;
Environment& mEnvironment;
World *mWorld;
PhysicsSystem *mPhysics;
MWRender::RenderingManager& mRendering;
void playerCellChange (Ptr::CellStore *cell, const ESM::Position& position,
bool adjustPlayerPos = true);
public:
Scene (Environment& environment, World *world, MWRender::MWScene& scene, PhysicsSystem *physics);
Scene (Environment& environment, World *world, MWRender::RenderingManager& rendering, PhysicsSystem *physics);
~Scene();
void unloadCell (CellRenderCollection::iterator iter);
void unloadCell (CellStoreCollection::iterator iter);
void loadCell (Ptr::CellStore *cell, MWRender::CellRender *render);
void loadCell (Ptr::CellStore *cell);
void changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos);
///< Move from exterior to interior or from interior cell to a different
@ -83,7 +87,7 @@ namespace MWWorld
Ptr::CellStore* getCurrentCell ();
const CellRenderCollection& getActiveCells () const;
const CellStoreCollection& getActiveCells () const;
bool hasCellChanged() const;
///< Has the player moved to a different cell, since the last frame?
@ -96,9 +100,8 @@ namespace MWWorld
void markCellAsUnchanged();
// std::string getFacedHandle();
void insertCell(ESMS::CellStore<MWWorld::RefData> &cell);
void insertCell(ESMS::CellStore<MWWorld::RefData> &cell, MWWorld::Environment& environment);
void advanceTime();
};
}

@ -7,8 +7,7 @@
#include <components/files/collections.hpp>
#include "../mwrender/sky.hpp"
#include "../mwrender/interior.hpp"
#include "../mwrender/exterior.hpp"
#include "../mwrender/player.hpp"
#include "../mwmechanics/mechanicsmanager.hpp"
@ -54,12 +53,13 @@ namespace
for (iterator iter (refList.list.begin()); iter!=refList.list.end(); ++iter)
{
if(iter->mData.getBaseNode()){
if (iter->mData.getHandle()==handle)
{
return &*iter;
}
}
}
return 0;
}
}
@ -71,75 +71,46 @@ namespace MWWorld
if (ESMS::LiveCellRef<ESM::Activator, RefData> *ref =
searchViaHandle (handle, cell.activators))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Potion, RefData> *ref = searchViaHandle (handle, cell.potions))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Apparatus, RefData> *ref = searchViaHandle (handle, cell.appas))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Armor, RefData> *ref = searchViaHandle (handle, cell.armors))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Book, RefData> *ref = searchViaHandle (handle, cell.books))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Clothing, RefData> *ref = searchViaHandle (handle, cell.clothes))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Container, RefData> *ref =
searchViaHandle (handle, cell.containers))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Creature, RefData> *ref =
searchViaHandle (handle, cell.creatures))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Door, RefData> *ref = searchViaHandle (handle, cell.doors))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Ingredient, RefData> *ref =
searchViaHandle (handle, cell.ingreds))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Light, RefData> *ref = searchViaHandle (handle, cell.lights))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Tool, RefData> *ref = searchViaHandle (handle, cell.lockpicks))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Miscellaneous, RefData> *ref = searchViaHandle (handle, cell.miscItems))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::NPC, RefData> *ref = searchViaHandle (handle, cell.npcs))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Probe, RefData> *ref = searchViaHandle (handle, cell.probes))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Repair, RefData> *ref = searchViaHandle (handle, cell.repairs))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Static, RefData> *ref = searchViaHandle (handle, cell.statics))
return Ptr (ref, &cell);
if (ESMS::LiveCellRef<ESM::Weapon, RefData> *ref = searchViaHandle (handle, cell.weapons))
return Ptr (ref, &cell);
return Ptr();
}
MWRender::CellRender *World::searchRender (Ptr::CellStore *store)
{
Scene::CellRenderCollection::const_iterator iter = mWorldScene->getActiveCells().find (store);
if (iter!=mWorldScene->getActiveCells().end())
{
return iter->second;
}
return 0;
}
int World::getDaysPerMonth (int month) const
{
@ -176,7 +147,7 @@ namespace MWWorld
const Files::Collections& fileCollections,
const std::string& master, const boost::filesystem::path& resDir,
bool newGame, Environment& environment, const std::string& encoding)
: mScene (renderer,physEng), mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0),
: mRendering (renderer,resDir, physEng, environment),mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0),
mSky (false), mEnvironment (environment), mNextDynamicRecord (0), mCells (mStore, mEsm, *this)
{
mPhysEngine = physEng;
@ -192,7 +163,8 @@ namespace MWWorld
mEsm.open (masterPath.string());
mStore.load (mEsm);
mPlayer = new MWWorld::Player (mScene.getPlayer(), mStore.npcs.find ("player"), *this);
MWRender::Player* play = &(mRendering.getPlayer());
mPlayer = new MWWorld::Player (play, mStore.npcs.find ("player"), *this);
mPhysics->addActor (mPlayer->getPlayer().getRefData().getHandle(), "", Ogre::Vector3 (0, 0, 0));
// global variables
@ -206,18 +178,18 @@ namespace MWWorld
mPhysEngine = physEng;
mWorldScene = new Scene(environment, this, mScene, mPhysics);
mRenderingManager = new MWRender::RenderingManager(
MWRender::SkyManager::create(renderer.getWindow(), mScene.getCamera(), resDir)
);
mWorldScene = new Scene(environment, this, mRendering, mPhysics);
}
World::~World()
{
delete mWorldScene;
delete mGlobalVariables;
delete mPlayer;
delete mPhysics;
delete mPlayer;
}
const ESM::Cell *World::getExterior (const std::string& cellName) const
@ -303,10 +275,11 @@ namespace MWWorld
}
// active cells
for (Scene::CellRenderCollection::const_iterator iter (mWorldScene->getActiveCells().begin());
for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin());
iter!=mWorldScene->getActiveCells().end(); ++iter)
{
Ptr ptr = mCells.getPtr (name, *iter->first);
Ptr::CellStore* cellstore = *iter;
Ptr ptr = mCells.getPtr (name, *cellstore);
if (!ptr.isEmpty())
return ptr;
@ -327,11 +300,11 @@ namespace MWWorld
{
if (mPlayer->getPlayer().getRefData().getHandle()==handle)
return mPlayer->getPlayer();
for (Scene::CellRenderCollection::const_iterator iter (mWorldScene->getActiveCells().begin());
for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin());
iter!=mWorldScene->getActiveCells().end(); ++iter)
{
Ptr ptr = getPtrViaHandle (handle, *iter->first);
Ptr::CellStore* cellstore = *iter;
Ptr ptr = getPtrViaHandle (handle, *cellstore);
if (!ptr.isEmpty())
return ptr;
@ -346,13 +319,12 @@ namespace MWWorld
{
reference.getRefData().enable();
if (MWRender::CellRender *render = searchRender (reference.getCell()))
{
render->enable (reference.getRefData().getHandle());
if (mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end())
Class::get (reference).enable (reference, mEnvironment);
}
//render->enable (reference.getRefData().getHandle());
if(mWorldScene->getActiveCells().find (reference.getCell()) != mWorldScene->getActiveCells().end())
Class::get (reference).enable (reference, mEnvironment);
}
}
@ -362,29 +334,28 @@ namespace MWWorld
{
reference.getRefData().disable();
if (MWRender::CellRender *render = searchRender (reference.getCell()))
{
render->disable (reference.getRefData().getHandle());
if (mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end())
{
Class::get (reference).disable (reference, mEnvironment);
mEnvironment.mSoundManager->stopSound3D (reference);
}
//render->disable (reference.getRefData().getHandle());
if(mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end()){
Class::get (reference).disable (reference, mEnvironment);
mEnvironment.mSoundManager->stopSound3D (reference);
}
}
}
void World::advanceTime (double hours)
{
hours += mGlobalVariables->getFloat ("gamehour");
setHour (hours);
int days = hours / 24;
if (days>0)
mGlobalVariables->setInt ("dayspassed", days + mGlobalVariables->getInt ("dayspassed"));
mWorldScene->advanceTime();
}
void World::setHour (double hour)
@ -398,7 +369,7 @@ namespace MWWorld
mGlobalVariables->setFloat ("gamehour", hour);
mRenderingManager->skySetHour (hour);
mRendering.skySetHour (hour);
if (days>0)
setDay (days + mGlobalVariables->getInt ("day"));
@ -433,7 +404,7 @@ namespace MWWorld
mGlobalVariables->setInt ("day", day);
mGlobalVariables->setInt ("month", month);
mRenderingManager->skySetDate (day, month);
mRendering.skySetDate (day, month);
}
void World::setMonth (int month)
@ -454,7 +425,7 @@ namespace MWWorld
if (years>0)
mGlobalVariables->setInt ("year", years+mGlobalVariables->getInt ("year"));
mRenderingManager->skySetDate (mGlobalVariables->getInt ("day"), month);
mRendering.skySetDate (mGlobalVariables->getInt ("day"), month);
}
bool World::toggleSky()
@ -462,34 +433,34 @@ namespace MWWorld
if (mSky)
{
mSky = false;
mRenderingManager->skyDisable();
mRendering.skyDisable();
return false;
}
else
{
mSky = true;
// TODO check for extorior or interior with sky.
mRenderingManager->skySetHour (mGlobalVariables->getFloat ("gamehour"));
mRenderingManager->skySetDate (mGlobalVariables->getInt ("day"),
mRendering.skySetHour (mGlobalVariables->getFloat ("gamehour"));
mRendering.skySetDate (mGlobalVariables->getInt ("day"),
mGlobalVariables->getInt ("month"));
mRenderingManager->skyEnable();
mRendering.skyEnable();
return true;
}
}
int World::getMasserPhase() const
{
return mRenderingManager->skyGetMasserPhase();
return mRendering.skyGetMasserPhase();
}
int World::getSecundaPhase() const
{
return mRenderingManager->skyGetSecundaPhase();
return mRendering.skyGetSecundaPhase();
}
void World::setMoonColour (bool red)
{
mRenderingManager->skySetMoonColour (red);
mRendering.skySetMoonColour (red);
}
float World::getTimeScaleFactor() const
@ -514,7 +485,7 @@ namespace MWWorld
std::string World::getFacedHandle()
{
std::pair<std::string, float> result = mScene.getFacedHandle (*this);
std::pair<std::string, float> result = mPhysics->getFacedHandle (*this);
if (result.first.empty() ||
result.second>getStore().gameSettings.find ("iMaxActivateDist")->i)
@ -529,21 +500,16 @@ namespace MWWorld
{
ptr.getRefData().setCount (0);
if (MWRender::CellRender *render = searchRender (ptr.getCell()))
{
if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end())
{
Class::get (ptr).disable (ptr, mEnvironment);
mEnvironment.mSoundManager->stopSound3D (ptr);
mPhysics->removeObject (ptr.getRefData().getHandle());
if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end()){
// Class::get (ptr).disable (ptr, mEnvironment); /// \todo this line needs to be removed
mEnvironment.mSoundManager->stopSound3D (ptr);
mLocalScripts.remove (ptr);
}
mPhysics->removeObject (ptr.getRefData().getHandle());
mRendering.removeObject(ptr);
render->deleteObject (ptr.getRefData().getHandle());
ptr.getRefData().setHandle ("");
}
mLocalScripts.remove (ptr);
}
}
}
@ -575,11 +541,9 @@ namespace MWWorld
}
}
// \todo cell change for non-player ref
/// \todo cell change for non-player ref
// \todo this should go into the new scene class and eventually into the objects/actors classes.
mScene.getMgr()->getSceneNode (ptr.getRefData().getHandle())->
setPosition (Ogre::Vector3 (x, y, z));
mRendering.moveObject (ptr, Ogre::Vector3 (x, y, z));
}
void World::moveObject (Ptr ptr, float x, float y, float z)
@ -653,7 +617,7 @@ namespace MWWorld
bool World::toggleRenderMode (RenderMode mode)
{
return mScene.toggleRenderMode (mode);
return mRendering.toggleRenderMode (mode);
}
std::pair<std::string, const ESM::Potion *> World::createRecord (const ESM::Potion& record)
@ -710,4 +674,21 @@ namespace MWWorld
return cell;
}
}
void World::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode,
int number)
{
mRendering.playAnimationGroup (ptr, groupName, mode, number);
}
void World::skipAnimation (const MWWorld::Ptr& ptr)
{
mRendering.skipAnimation (ptr);
}
void World::setObjectPhysicsRotation(const std::string& handle, Ogre::Quaternion quat){
mPhysics->rotateObject(handle, quat);
}
void World::setObjectPhysicsPosition(const std::string& handle, Ogre::Vector3 vec){
mPhysics->moveObject(handle, vec);
}
}

@ -8,8 +8,8 @@
#include <components/esm_store/cell_store.hpp>
#include "../mwrender/mwscene.hpp"
#include "../mwrender/rendering_manager.hpp"
#include "../mwrender/debugging.hpp"
#include "../mwrender/renderingmanager.hpp"
#include "refdata.hpp"
#include "ptr.hpp"
@ -65,7 +65,8 @@ namespace MWWorld
private:
MWRender::MWScene mScene;
MWRender::RenderingManager mRendering;
MWWorld::Scene *mWorldScene;
MWWorld::Player *mPlayer;
ESM::ESMReader mEsm;
@ -75,7 +76,6 @@ namespace MWWorld
MWWorld::PhysicsSystem *mPhysics;
bool mSky;
Environment& mEnvironment;
MWRender::RenderingManager *mRenderingManager;
int mNextDynamicRecord;
Cells mCells;
@ -88,7 +88,6 @@ namespace MWWorld
Ptr getPtrViaHandle (const std::string& handle, Ptr::CellStore& cellStore);
MWRender::CellRender *searchRender (Ptr::CellStore *store);
int getDaysPerMonth (int month) const;
@ -134,8 +133,10 @@ namespace MWWorld
Ptr getPtrViaHandle (const std::string& handle);
///< Return a pointer to a liveCellRef with the given Ogre handle.
/// \todo enable reference in the OGRE scene
void enable (Ptr reference);
/// \todo 5disable reference in the OGRE scene
void disable (Ptr reference);
void advanceTime (double hours);
@ -205,6 +206,20 @@ namespace MWWorld
const ESM::Cell *createRecord (const ESM::Cell& record);
///< Create a new recrod (of type cell) in the ESM store.
/// \return ID, pointer to created record
void playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode,
int number = 1);
///< Run animation for a MW-reference. Calls to this function for references that are
/// currently not in the rendered scene should be ignored.
///
/// \param mode: 0 normal, 1 immediate start, 2 immediate loop
/// \param number How offen the animation should be run
void skipAnimation (const MWWorld::Ptr& ptr);
///< Skip the animation for the given MW-reference for one frame. Calls to this function for
/// references that are currently not in the rendered scene should be ignored.
void setObjectPhysicsRotation(const std::string& handle,Ogre::Quaternion quat);
void setObjectPhysicsPosition(const std::string& handle,Ogre::Vector3 vector);
};
}

@ -240,15 +240,36 @@ public:
// should not have been declared const in the first place.
BSAFile *narc = (BSAFile*)&arc;
String passed = filename;
if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
|| filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':'
|| filename.at(filename.length() - 1) == '|')
{
passed = filename.substr(0, filename.length() - 2);
}
if(filename.at(filename.length() - 2) == '>')
passed = filename.substr(0, filename.length() - 6);
// Open the file
StreamPtr strm = narc->getFile(filename.c_str());
StreamPtr strm = narc->getFile(passed.c_str());
// Wrap it into an Ogre::DataStream.
return DataStreamPtr(new Mangle2OgreStream(strm));
}
// Check if the file exists.
bool exists(const String& filename) { return arc.exists(filename.c_str()); }
bool exists(const String& filename) {
String passed = filename;
if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
|| filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':'
|| filename.at(filename.length() - 1) == '|')
{
passed = filename.substr(0, filename.length() - 2);
}
if(filename.at(filename.length() - 2) == '>')
passed = filename.substr(0, filename.length() - 6);
return arc.exists(passed.c_str());
}
time_t getModifiedTime(const String&) { return 0; }
// This is never called as far as I can see.

@ -187,7 +187,7 @@ namespace ESMS
++iter)
if (!functor (iter->ref, iter->mData))
return false;
return true;
}

@ -26,6 +26,7 @@
#include "controlled.hpp"
#include <iostream>
#include <Ogre.h>
namespace Nif
{
@ -366,6 +367,12 @@ public:
Vector trans; // Translation
float scale; // Probably scale (always 1)
};
struct BoneTrafoCopy
{
Ogre::Quaternion rotation;
Ogre::Vector3 trans;
float scale;
};
struct VertWeight
{
@ -380,6 +387,19 @@ public:
const Vector4 *unknown;
Misc::SliceArray<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;
std::vector<BoneInfo> bones;
@ -412,92 +432,396 @@ public:
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:
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 vertCount = nif->getInt();
nif->getByte();
for(int i=0; i<morphCount; i++)
{
int magic = nif->getInt();
nif->getInt();
if(magic)
// Time, data, forward, backward tangents
nif->getFloatLen(4*magic);
nif->getFloatLen(vertCount*3);
int magic = nif->getInt();
int type = nif->getInt();
for(int i = 0; i < vertCount; i++){
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
{
public:
void read(NIFFile *nif)
{
// Rotations first
int count = nif->getInt();
if(count)
{
int type = nif->getInt();
if(type == 1)
nif->skip(count*4*5); // time + quaternion
else if(type == 3)
nif->skip(count*4*8); // rot1 + tension+bias+continuity
else if(type == 4)
{
for(int j=0;j<count;j++)
{
nif->getFloat(); // time
for(int i=0; i<3; i++)
{
int cnt = nif->getInt();
int type = nif->getInt();
if(type == 1)
nif->skip(cnt*4*2); // time + unknown
else if(type == 2)
nif->skip(cnt*4*4); // time + unknown vector
else nif->fail("Unknown sub-rotation type");
}
}
}
else nif->fail("Unknown rotation type in NiKeyframeData");
}
// Then translation
count = nif->getInt();
if(count)
{
int type = nif->getInt();
if(type == 1)
nif->getFloatLen(count*4); // time + translation
else if(type == 2)
nif->getFloatLen(count*10); // trans1 + forward + backward
else if(type == 3)
nif->getFloatLen(count*7); // trans1 + tension,bias,continuity
else nif->fail("Unknown translation type");
}
// Finally, scalings
count = nif->getInt();
if(count)
{
int type = nif->getInt();
int size = 0;
if(type == 1) size = 2; // time+scale
else if(type == 2) size = 4; // 1 + forward + backward (floats)
else if(type == 3) size = 5; // 1 + tbc
else nif->fail("Unknown scaling type");
nif->getFloatLen(count*size);
}
}
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)
{
// Rotations first
int count = nif->getInt();
//std::vector<Ogre::Quaternion> quat(count);
//std::vector<float> rottime(count);
if(count)
{
//TYPE1 LINEAR_KEY
//TYPE2 QUADRATIC_KEY
//TYPE3 TBC_KEY
//TYPE4 XYZ_ROTATION_KEY
//TYPE5 UNKNOWN_KEY
rtype = nif->getInt();
//std::cout << "Count: " << count << "Type: " << type << "\n";
if(rtype == 1)
{
//We need to actually read in these values instead of skipping them
//nif->skip(count*4*5); // time + quaternion
for (int i = 0; i < count; i++) {
float time = nif->getFloat();
float w = nif->getFloat();
float x = nif->getFloat();
float y = nif->getFloat();
float z = nif->getFloat();
Ogre::Quaternion quat = Ogre::Quaternion(Ogre::Real(w), Ogre::Real(x), Ogre::Real(y), Ogre::Real(z));
quats.push_back(quat);
rottime.push_back(time);
//if(time == 0.0 || time > 355.5)
// std::cout <<"Time:" << time << "W:" << w <<"X:" << x << "Y:" << y << "Z:" << z << "\n";
}
}
else if(rtype == 3)
{ //Example - node 116 in base_anim.nif
for (int i = 0; i < count; i++) {
float time = nif->getFloat();
float w = nif->getFloat();
float x = nif->getFloat();
float y = nif->getFloat();
float z = nif->getFloat();
float tbcx = nif->getFloat();
float tbcy = nif->getFloat();
float tbcz = nif->getFloat();
Ogre::Quaternion quat = Ogre::Quaternion(Ogre::Real(w), Ogre::Real(x), Ogre::Real(y), Ogre::Real(z));
Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz);
quats.push_back(quat);
rottime.push_back(time);
tbc.push_back(vec);
//if(time == 0.0 || time > 355.5)
// std::cout <<"Time:" << time << "W:" << w <<"X:" << x << "Y:" << y << "Z:" << z << "\n";
}
//nif->skip(count*4*8); // rot1 + tension+bias+continuity
}
else if(rtype == 4)
{
for(int j=0;j<count;j++)
{
nif->getFloat(); // time
for(int i=0; i<3; i++)
{
int cnt = nif->getInt();
int type = nif->getInt();
if(type == 1)
nif->skip(cnt*4*2); // time + unknown
else if(type == 2)
nif->skip(cnt*4*4); // time + unknown vector
else nif->fail("Unknown sub-rotation type");
}
}
}
else nif->fail("Unknown rotation type in NiKeyframeData");
}
//first = false;
// Then translation
count = nif->getInt();
if(count)
{
ttype = nif->getInt();
//std::cout << "TransCount:" << count << " Type: " << type << "\n";
if(ttype == 1) {
for (int i = 0; i < count; i++) {
float time = nif->getFloat();
float x = nif->getFloat();
float y = nif->getFloat();
float z = nif->getFloat();
Ogre::Vector3 trans = Ogre::Vector3(x, y, z);
translist1.push_back(trans);
transtime.push_back(time);
}
//nif->getFloatLen(count*4); // time + translation
}
else if(ttype == 2)
{ //Example - node 116 in base_anim.nif
for (int i = 0; i < count; i++) {
float time = nif->getFloat();
float x = nif->getFloat();
float y = nif->getFloat();
float z = nif->getFloat();
float x2 = nif->getFloat();
float y2 = nif->getFloat();
float z2 = nif->getFloat();
float x3 = nif->getFloat();
float y3 = nif->getFloat();
float z3 = nif->getFloat();
Ogre::Vector3 trans = Ogre::Vector3(x, y, z);
Ogre::Vector3 trans2 = Ogre::Vector3(x2, y2, z2);
Ogre::Vector3 trans3 = Ogre::Vector3(x3, y3, z3);
transtime.push_back(time);
translist1.push_back(trans);
translist2.push_back(trans2);
translist3.push_back(trans3);
}
//nif->getFloatLen(count*10); // trans1 + forward + backward
}
else if(ttype == 3){
for (int i = 0; i < count; i++) {
float time = nif->getFloat();
float x = nif->getFloat();
float y = nif->getFloat();
float z = nif->getFloat();
float t = nif->getFloat();
float b = nif->getFloat();
float c = nif->getFloat();
Ogre::Vector3 trans = Ogre::Vector3(x, y, z);
Ogre::Vector3 tbc = Ogre::Vector3(t, b, c);
translist1.push_back(trans);
transtbc.push_back(tbc);
transtime.push_back(time);
}
//nif->getFloatLen(count*7); // trans1 + tension,bias,continuity
}
else nif->fail("Unknown translation type");
}
// Finally, scalings
count = nif->getInt();
if(count)
{
stype = nif->getInt();
for(int i = 0; i < count; i++){
//int size = 0;
if(stype >= 1 && stype < 4)
{
float time = nif->getFloat();
float scale = nif->getFloat();
scaletime.push_back(time);
scalefactor.push_back(scale);
//size = 2; // time+scale
}
else nif->fail("Unknown scaling type");
if(stype == 2){
//size = 4; // 1 + forward + backward (floats)
float forward = nif->getFloat();
float backward = nif->getFloat();
forwards.push_back(forward);
backwards.push_back(backward);
}
else if(stype == 3){
float tbcx = nif->getFloat();
float tbcy = nif->getFloat();
float tbcz = nif->getFloat();
Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz);
tbcscale.push_back(vec);
//size = 5; // 1 + tbc
}
}
}
else
stype = 0;
}
int getRtype(){
return rtype;
}
int getStype(){
return stype;
}
int getTtype(){
return ttype;
}
float getStartTime(){
return startTime;
}
float getStopTime(){
return stopTime;
}
std::vector<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

@ -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
{
NodeList children;
@ -133,6 +147,27 @@ struct NiTriShape : Node
data.read(nif);
skin.read(nif);
}
NiTriShapeCopy clone(){
NiTriShapeCopy copy;
copy.sname = name.toString();
float *ptr = (float*)data->vertices.ptr;
float *ptrNormals = (float*)data->normals.ptr;
int numVerts = data->vertices.length / 3;
for(int i = 0; i < numVerts; i++)
{
float *current = (float*) (ptr + i * 3);
copy.vertices.push_back(Ogre::Vector3(*current, *(current + 1), *(current + 2)));
if(ptrNormals){
float *currentNormals = (float*) (ptrNormals + i * 3);
copy.normals.push_back(Ogre::Vector3(*currentNormals, *(currentNormals + 1), *(currentNormals + 2)));
}
}
return copy;
}
};
struct NiCamera : Node
@ -186,5 +221,7 @@ struct NiRotatingParticles : Node
}
};
} // Namespace
#endif

@ -24,25 +24,7 @@
//loadResource->handleNode->handleNiTriShape->createSubMesh
#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;
@ -219,6 +201,12 @@ static CompareFunction getTestMode(int mode)
}
*/
void NIFLoader::setOutputAnimFiles(bool output){
mOutputAnimFiles = output;
}
void NIFLoader::setVerbosePath(std::string path){
verbosePath = path;
}
void NIFLoader::createMaterial(const String &name,
const Vector &ambient,
const Vector &diffuse,
@ -230,11 +218,24 @@ void NIFLoader::createMaterial(const String &name,
{
MaterialPtr material = MaterialManager::getSingleton().create(name, resourceGroup);
//Hardware Skinning code, textures may be the wrong color if enabled
/*if(!mSkel.isNull()){
material->removeAllTechniques();
Ogre::Technique* tech = material->createTechnique();
//tech->setSchemeName("blahblah");
Pass* pass = tech->createPass();
pass->setVertexProgram("Ogre/HardwareSkinningFourWeights");
}*/
// This assigns the texture to this material. If the texture name is
// a file name, and this file exists (in a resource directory), it
// will automatically be loaded when needed. If not (such as for
// internal NIF textures that we might support later), we should
// already have inserted a manual loader for the texture.
if (!texName.empty())
{
Pass *pass = material->getTechnique(0)->getPass(0);
@ -294,6 +295,8 @@ void NIFLoader::createMaterial(const String &name,
material->setSpecular(specular.array[0], specular.array[1], specular.array[2], alpha);
material->setSelfIllumination(emissive.array[0], emissive.array[1], emissive.array[2]);
material->setShininess(glossiness);
}
// Takes a name and adds a unique part to it. This is just used to
@ -355,20 +358,69 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std
HardwareVertexBufferSharedPtr vbuf =
HardwareBufferManager::getSingleton().createVertexBuffer(
VertexElement::getTypeSize(VET_FLOAT3),
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, true);
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
if(flip)
{
float *datamod = new float[data->vertices.length];
//std::cout << "Shape" << shape->name.toString() << "\n";
for(int i = 0; i < numVerts; i++)
{
int index = i * 3;
const float *pos = data->vertices.ptr + index;
Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2));
original = mTransform * original;
mBoundingBox.merge(original);
datamod[index] = original.x;
datamod[index+1] = original.y;
datamod[index+2] = original.z;
}
vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false);
}
else
{
vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, false);
}
VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding;
bind->setBinding(nextBuf++, vbuf);
// Vertex normals
if (data->normals.length)
{
decl->addElement(nextBuf, 0, VET_FLOAT3, VES_NORMAL);
vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
VertexElement::getTypeSize(VET_FLOAT3),
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
vbuf->writeData(0, vbuf->getSizeInBytes(), data->normals.ptr, true);
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
if(flip)
{
Quaternion rotation = mTransform.extractQuaternion();
rotation.normalise();
float *datamod = new float[data->normals.length];
for(int i = 0; i < numVerts; i++)
{
int index = i * 3;
const float *pos = data->normals.ptr + index;
Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2));
original = rotation * original;
if (mNormaliseNormals)
{
original.normalise();
}
datamod[index] = original.x;
datamod[index+1] = original.y;
datamod[index+2] = original.z;
}
vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false);
}
else
{
vbuf->writeData(0, vbuf->getSizeInBytes(), data->normals.ptr, false);
}
bind->setBinding(nextBuf++, vbuf);
}
@ -393,30 +445,79 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std
bind->setBinding(nextBuf++, vbuf);
}
// Texture UV coordinates
if (data->uvlist.length)
if (data->uvlist.length)
{
decl->addElement(nextBuf, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES);
vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
VertexElement::getTypeSize(VET_FLOAT2),
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY,false);
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);
vbuf->writeData(0, vbuf->getSizeInBytes(), data->uvlist.ptr, true);
float y = *(data->uvlist.ptr + i + 1);
datamod[i] =x;
datamod[i + 1] =y;
}
vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false);
}
else
vbuf->writeData(0, vbuf->getSizeInBytes(), data->uvlist.ptr, false);
bind->setBinding(nextBuf++, vbuf);
}
// Triangle faces
// Triangle faces - The total number of triangle points
int numFaces = data->triangles.length;
if (numFaces)
{
sub->indexData->indexCount = numFaces;
sub->indexData->indexStart = 0;
HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
createIndexBuffer(HardwareIndexBuffer::IT_16BIT,
numFaces,
HardwareBuffer::HBU_STATIC_WRITE_ONLY);
ibuf->writeData(0, ibuf->getSizeInBytes(), data->triangles.ptr, true);
HardwareBuffer::HBU_STATIC_WRITE_ONLY, true);
if(flip && mFlipVertexWinding && sub->indexData->indexCount % 3 == 0){
sub->indexData->indexBuffer = ibuf;
uint16 *datamod = new uint16[numFaces];
int index = 0;
for (size_t i = 0; i < sub->indexData->indexCount; i+=3)
{
const short *pos = data->triangles.ptr + index;
uint16 i0 = (uint16) *(pos+0);
uint16 i1 = (uint16) *(pos+1);
uint16 i2 = (uint16) *(pos+2);
//std::cout << "i0: " << i0 << "i1: " << i1 << "i2: " << i2 << "\n";
datamod[index] = i2;
datamod[index+1] = i1;
datamod[index+2] = i0;
index += 3;
}
ibuf->writeData(0, ibuf->getSizeInBytes(), datamod, false);
}
else
ibuf->writeData(0, ibuf->getSizeInBytes(), data->triangles.ptr, false);
sub->indexData->indexBuffer = ibuf;
sub->indexData->indexCount = numFaces;
sub->indexData->indexStart = 0;
}
// Set material if one was given
@ -475,7 +576,7 @@ static void vectorMul(const Matrix &A, float *C)
}
void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bounds)
void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bounds, Transformation original, std::vector<std::string> boneSequence)
{
assert(shape != NULL);
@ -636,11 +737,29 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
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.
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<Ogre::Vector3> vertexPosOriginal(numVerts, Ogre::Vector3::ZERO);
std::vector<Ogre::Vector3> vertexNormalOriginal(numVerts, Ogre::Vector3::ZERO);
float *ptrNormals = (float*)data->normals.ptr;
//the bone from skin->bones[boneIndex] is linked to skin->data->bones[boneIndex]
@ -667,24 +786,50 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
break;
}
//get the bone from bones array of skindata
if(!mSkel->hasBone(shape->skin->bones[boneIndex].name.toString()))
std::cout << "We don't have this bone";
bonePtr = mSkel->getBone(shape->skin->bones[boneIndex].name.toString());
// final_vector = old_vector + old_rotation*new_vector*old_scale
vecPos = bonePtr->_getDerivedPosition() +
bonePtr->_getDerivedOrientation() * convertVector3(it->trafo->trans);
vecRot = bonePtr->_getDerivedOrientation() * convertRotation(it->trafo->rotation);
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() +
bonePtr->_getDerivedOrientation() * convertVector3(it->trafo->trans);
vecRot = bonePtr->_getDerivedOrientation() * convertRotation(it->trafo->rotation);
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?
if (vertexPosAbsolut[verIndex] == false)
{
//apply transformation to the vertices
Vector3 absVertPos = vecPos + vecRot * Vector3(ptr + verIndex *3);
absVertPos = absVertPos * (it->weights.ptr + i)->weight;
vertexPosOriginal[verIndex] = Vector3(ptr + verIndex *3);
mBoundingBox.merge(absVertPos);
//convert it back to float *
for (int j=0; j<3; j++)
(ptr + verIndex*3)[j] = absVertPos[j];
@ -694,6 +839,8 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
if (verIndex < data->normals.length)
{
Vector3 absNormalsPos = vecRot * Vector3(ptrNormals + verIndex *3);
absNormalsPos = absNormalsPos * (it->weights.ptr + i)->weight;
vertexNormalOriginal[verIndex] = Vector3(ptrNormals + verIndex *3);
for (int j=0; j<3; j++)
(ptrNormals + verIndex*3)[j] = absNormalsPos[j];
@ -701,27 +848,67 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
vertexPosAbsolut[verIndex] = true;
}
else
{
Vector3 absVertPos = vecPos + vecRot * vertexPosOriginal[verIndex];
absVertPos = absVertPos * (it->weights.ptr + i)->weight;
Vector3 old = Vector3(ptr + verIndex *3);
absVertPos = absVertPos + old;
mBoundingBox.merge(absVertPos);
//convert it back to float *
for (int j=0; j<3; j++)
(ptr + verIndex*3)[j] = absVertPos[j];
//apply rotation to the normals (not every vertex has a normal)
//FIXME: I guessed that vertex[i] = normal[i], is that true?
if (verIndex < data->normals.length)
{
Vector3 absNormalsPos = vecRot * vertexNormalOriginal[verIndex];
absNormalsPos = absNormalsPos * (it->weights.ptr + i)->weight;
Vector3 oldNormal = Vector3(ptrNormals + verIndex *3);
absNormalsPos = absNormalsPos + oldNormal;
for (int j=0; j<3; j++)
(ptrNormals + verIndex*3)[j] = absNormalsPos[j];
}
}
VertexBoneAssignment vba;
vba.boneIndex = bonePtr->getHandle();
vba.vertexIndex = verIndex;
vba.weight = (it->weights.ptr + i)->weight;
vertexBoneAssignments.push_back(vba);
}
boneIndex++;
}
}
else
{
copy.boneSequence = boneSequence;
// Rotate, scale and translate all the vertices,
const Matrix &rot = shape->trafo->rotation;
const Vector &pos = shape->trafo->pos;
float scale = shape->trafo->scale;
copy.trafo.trans = convertVector3(original.pos);
copy.trafo.rotation = convertRotation(original.rotation);
copy.trafo.scale = original.scale;
//We don't use velocity for anything yet, so it does not need to be saved
// Computes C = B + AxC*scale
for (int i=0; i<numVerts; i++)
{
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;
}
@ -735,24 +922,58 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
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)
{
// Add this vertex set to the bounding box
bounds.add(optr, numVerts);
shapes.push_back(copy);
// Create the submesh
createOgreSubMesh(shape, material, vertexBoneAssignments);
}
}
void NIFLoader::calculateTransform()
{
// Calculate transform
Matrix4 transform = Matrix4::IDENTITY;
transform = Matrix4::getScale(vector) * transform;
// Check whether we have to flip vertex winding.
// We do have to, if we changed our right hand base.
// We can test it by using the cross product from X and Y and see, if it is a non-negative
// projection on Z. Actually it should be exactly Z, as we don't do non-uniform scaling yet,
// but the test is cheap either way.
Matrix3 m3;
transform.extract3x3Matrix(m3);
if (m3.GetColumn(0).crossProduct(m3.GetColumn(1)).dotProduct(m3.GetColumn(2)) < 0)
{
mFlipVertexWinding = true;
}
mTransform = transform;
}
void NIFLoader::handleNode(Nif::Node *node, int flags,
const Transformation *trafo, BoundsFinder &bounds, Bone *parentBone)
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
// the flags we currently use, at least.
flags |= node->flags;
@ -780,6 +1001,58 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
// the engine, just skip this entire node.
return;
}
if (e->recType == RC_NiTextKeyExtraData){
Nif::NiTextKeyExtraData* extra = dynamic_cast<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;
@ -790,20 +1063,15 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
//FIXME: "Bip01" isn't every time the root bone
if (node->name == "Bip01" || node->name == "Root Bone") //root node, create a skeleton
{
mSkel = SkeletonManager::getSingleton().create(getSkeletonName(), resourceGroup, true);
/*if (node->extra->recType == RC_NiTextKeyExtraData )
{
//TODO: Get animation names
std::cout << node->name.toString() << " is root bone and has textkeyextradata!\n";
}*/
mSkel = SkeletonManager::getSingleton().create(getSkeletonName(), resourceGroup, true);
}
if (!mSkel.isNull()) //if there is a skeleton
{
std::string name = node->name.toString();
//if (isBeast && isChest)
// std::cout << "NAME: " << name << "\n";
boneSequence.push_back(name);
// Quick-n-dirty workaround for the fact that several
// bones may have the same name.
if(!mSkel->hasBone(name))
@ -819,7 +1087,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
}
}
}
Transformation original = *(node->trafo);
// Apply the parent transformation to this node. We overwrite the
// existing data with the final transformation.
if (trafo)
@ -846,201 +1114,97 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
{
NodeList &list = ((NiNode*)node)->children;
int n = list.length();
int i = 0;
if(isHands){
//cout << "NumberOfNs: " << n << "Stack:" << stack << "\n";
//if(stack == 3)
//n=0;
}
for (; i<n; i++)
for (int i = 0; i<n; 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
/*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 (isChest)
//std::cout << "NAME: " << name << "\n";
std::string nodename = node->name.toString();
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)
if (triname == "")
{
handleNiTriShape(dynamic_cast<NiTriShape*>(node), flags, bounds);
handleNiTriShape(dynamic_cast<NiTriShape*>(node), flags, bounds, original, boneSequence);
}
//if(isBeast && isChest)
//cout << "Handling Shape, Stack " << stack <<"\n";
counter++;
}
/*if(isHands){
//cout << "Handling Shape, Stack " << stack <<"\n";
counter++;
}*/
else if(nodename.length() >= triname.length())
{
std::transform(nodename.begin(), nodename.end(), nodename.begin(), ::tolower);
if(triname == nodename.substr(0, triname.length()))
handleNiTriShape(dynamic_cast<NiTriShape*>(node), flags, bounds, original, boneSequence);
}
}
stack--;
}
void NIFLoader::loadResource(Resource *resource)
{
if(skincounter == 1000)
skincounter = 0;
stack = 0;
counter = 0;
std::string name = resource->getName();
if(resourceName.compare(name) != 0)
{
skincounter = 0;
resourceName = name;
}
//std::cout <<"NAME:" << name;
//if(name.length() >= 20)
// {std::string split = name.substr(name.length() - 20, 20);
//if(name ==
//std::cout <<"NAME:" << name << "LEN: " << name.length() << "\n";
const std::string test ="meshes\\b\\B_N_Dark Elf_M_Skins.NIF";
const std::string test2 ="meshes\\b\\B_N_Dark Elf_M_Skins.nif";
const std::string test3 ="meshes\\b\\B_N_Redguard_F_Skins.NIF";
const std::string test4 ="meshes\\b\\B_N_Redguard_F_Skins.nif";
const std::string test5 ="meshes\\b\\B_N_Dark Elf_F_Skins.nif";
const std::string test6 ="meshes\\b\\B_N_Redguard_M_Skins.nif";
const std::string test7 ="meshes\\b\\B_N_Wood Elf_F_Skins.nif";
const std::string test8 ="meshes\\b\\B_N_Wood Elf_M_Skins.nif";
const std::string test9 ="meshes\\b\\B_N_Imperial_F_Skins.nif";
const std::string test10 ="meshes\\b\\B_N_Imperial_M_Skins.nif";
const std::string test11 ="meshes\\b\\B_N_Khajiit_F_Skins.nif";
const std::string test12 ="meshes\\b\\B_N_Khajiit_M_Skins.nif";
const std::string test13 ="meshes\\b\\B_N_Argonian_F_Skins.nif";
const std::string test14 ="meshes\\b\\B_N_Argonian_M_Skins.nif";
const std::string test15 ="meshes\\b\\B_N_Nord_F_Skins.nif";
const std::string test16 ="meshes\\b\\B_N_Nord_M_Skins.nif";
const std::string test17 ="meshes\\b\\B_N_Imperial_F_Skins.nif";
const std::string test18 ="meshes\\b\\B_N_Imperial_M_Skins.nif";
const std::string test19 ="meshes\\b\\B_N_Orc_F_Skins.nif";
const std::string test20 ="meshes\\b\\B_N_Orc_M_Skins.nif";
const std::string test21 ="meshes\\b\\B_N_Breton_F_Skins.nif";
const std::string test22 ="meshes\\b\\B_N_Breton_M_Skins.nif";
const std::string test23 ="meshes\\b\\B_N_High Elf_F_Skins.nif";
const std::string test24 ="meshes\\b\\B_N_High Elf_M_Skins.nif";
//std::cout <<"LEN1:" << test.length() << "TEST: " << test << "\n";
if(name.compare(test) == 0 || name.compare(test2) == 0 || name.compare(test3) == 0 || name.compare(test4) == 0 ||
name.compare(test5) == 0 || name.compare(test6) == 0 || name.compare(test7) == 0 || name.compare(test8) == 0 || name.compare(test9) == 0 ||
name.compare(test10) == 0 || name.compare(test11) == 0 || name.compare(test12) == 0 || name.compare(test13) == 0 ||
name.compare(test14) == 0 || name.compare(test15) == 0 || name.compare(test16) == 0 || name.compare(test17) == 0 ||
name.compare(test18) == 0 || name.compare(test19) == 0 || name.compare(test20) == 0 || name.compare(test21) == 0 ||
name.compare(test22) == 0 || name.compare(test23) == 0 || name.compare(test24) == 0
){
//std::cout << "Welcome Chest\n";
isChest = true;
if(name.compare(test11) == 0 || name.compare(test12) == 0 || name.compare(test13) == 0 || name.compare(test14) == 0)
{
isBeast = true;
//std::cout << "Welcome Beast\n";
}
else
isBeast = false;
}
else
isChest = false;
const std::string hands ="meshes\\b\\B_N_Dark Elf_M_Hands.1st.NIF";
const std::string hands2 ="meshes\\b\\B_N_Dark Elf_F_Hands.1st.NIF";
const std::string hands3 ="meshes\\b\\B_N_Redguard_M_Hands.1st.nif";
const std::string hands4 ="meshes\\b\\B_N_Redguard_F_Hands.1st.nif";
const std::string hands5 ="meshes\\b\\b_n_argonian_m_hands.1st.nif";
const std::string hands6 ="meshes\\b\\b_n_argonian_f_hands.1st.nif";
const std::string hands7 ="meshes\\b\\B_N_Breton_M_Hand.1st.NIF";
const std::string hands8 ="meshes\\b\\B_N_Breton_F_Hands.1st.nif";
const std::string hands9 ="meshes\\b\\B_N_High Elf_M_Hands.1st.nif";
const std::string hands10 ="meshes\\b\\B_N_High Elf_F_Hands.1st.nif";
const std::string hands11 ="meshes\\b\\B_N_Nord_M_Hands.1st.nif";
const std::string hands12 ="meshes\\b\\B_N_Nord_F_Hands.1st.nif";
const std::string hands13 ="meshes\\b\\b_n_khajiit_m_hands.1st.nif";
const std::string hands14 ="meshes\\b\\b_n_khajiit_f_hands.1st.nif";
const std::string hands15 ="meshes\\b\\B_N_Orc_M_Hands.1st.nif";
const std::string hands16 ="meshes\\b\\B_N_Orc_F_Hands.1st.nif";
const std::string hands17 ="meshes\\b\\B_N_Wood Elf_M_Hands.1st.nif";
const std::string hands18 ="meshes\\b\\B_N_Wood Elf_F_Hands.1st.nif";
const std::string hands19 ="meshes\\b\\B_N_Imperial_M_Hands.1st.nif";
const std::string hands20 ="meshes\\b\\B_N_Imperial_F_Hands.1st.nif";
if(name.compare(hands) == 0 || name.compare(hands2) == 0 || name.compare(hands3) == 0 || name.compare(hands4) == 0 ||
name.compare(hands5) == 0 || name.compare(hands6) == 0 || name.compare(hands7) == 0 || name.compare(hands8) == 0 ||
name.compare(hands9) == 0 || name.compare(hands10) == 0 || name.compare(hands11) == 0 || name.compare(hands12) == 0 ||
name.compare(hands13) == 0 || name.compare(hands14) == 0 || name.compare(hands15) == 0 || name.compare(hands16) == 0 ||
name.compare(hands17) == 0 || name.compare(hands18) == 0 || name.compare(hands19) == 0 || name.compare(hands20) == 0)
{
//std::cout << "Welcome Hands1st\n";
isHands = true;
isChest = false;
}
else
isHands = false;
/*
else if(name.compare(test3) == 0 || name.compare(test4) == 0)
{
std::cout << "\n\n\nWelcome FRedguard Chest\n\n\n";
isChest = true;
}
else if(name.compare(test5) == 0 || name.compare(test6) == 0)
{
std::cout << "\n\n\nWelcome FRedguard Chest\n\n\n";
isChest = true;
}
else if(name.compare(test7) == 0 || name.compare(test8) == 0)
{
std::cout << "\n\n\nWelcome FRedguard Chest\n\n\n";
isChest = true;
}
else if(name.compare(test9) == 0 || name.compare(test10) == 0)
{
std::cout << "\n\n\nWelcome FRedguard Chest\n\n\n";
isChest = true;
}*/
//if(split== "Skins.NIF")
// std::cout << "\nSPECIAL PROPS\n";
resourceName = "";
// Check if the resource already exists
//MeshPtr ptr = m->load(name, "custom");
//cout << "THISNAME: " << ptr->getName() << "\n";
//cout << "RESOURCE:"<< resource->getName();
allanim.clear();
shapes.clear();
mBoundingBox.setNull();
mesh = 0;
mSkel.setNull();
flip = false;
name = resource->getName();
char suffix = name.at(name.length() - 2);
bool addAnim = true;
bool hasAnim = false;
bool baddin = false;
bNiTri = true;
if(suffix == '*')
{
vector = Ogre::Vector3(-1,1,1);
flip = true;
}
else if(suffix == '?'){
vector = Ogre::Vector3(1,-1,1);
flip = true;
}
else if(suffix == '<'){
vector = Ogre::Vector3(1,1,-1);
flip = true;
}
else if(suffix == '>')
{
baddin = true;
bNiTri = true;
std::string sub = name.substr(name.length() - 6, 4);
if(sub.compare("0000") != 0)
addAnim = false;
}
switch(name.at(name.length() - 1))
{
case '"':
triname = "tri chest";
break;
case '*':
triname = "tri tail";
break;
case ':':
triname = "tri left foot";
break;
case '<':
triname = "tri right foot";
break;
case '>':
triname = "tri left hand";
break;
case '?':
triname = "tri right hand";
break;
default:
triname = "";
break;
}
if(flip)
{
calculateTransform();
}
// Set up the VFS if it hasn't been done already
if (!vfs) vfs = new OgreVFS(resourceGroup);
@ -1087,8 +1251,33 @@ void NIFLoader::loadResource(Resource *resource)
}
// Handle the node
handleNode(node, 0, NULL, bounds, 0);
std::vector<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.
if (bounds.isValid())
{
@ -1096,63 +1285,83 @@ void NIFLoader::loadResource(Resource *resource)
bounds.maxX(), bounds.maxY(), bounds.maxZ()));
mesh->_setBoundingSphereRadius(bounds.getRadius());
}
if(hasAnim && addAnim){
allanimmap[name] = allanim;
alltextmappings[name] = textmappings;
}
if(!mSkel.isNull() && shapes.size() > 0 && addAnim)
{
allshapesmap[name] = shapes;
// set skeleton
// if (!skel.isNull())
// mesh->setSkeletonName(getSkeletonName());
}
if(flip){
mesh->_setBounds(mBoundingBox, false);
}
if (!mSkel.isNull())
{
mesh->_notifySkeleton(mSkel);
}
}
void NIFLoader::addInMesh(Ogre::Mesh* input){
addin.push_back(input);
}
MeshPtr NIFLoader::load(const std::string &name,
const std::string &group)
{
MeshManager *m = MeshManager::getSingletonPtr();
// Check if the resource already exists
ResourcePtr ptr = m->getByName(name, group);
MeshPtr resize;
const std::string beast1 ="meshes\\b\\B_N_Khajiit_F_Skins.nif";
const std::string beast2 ="meshes\\b\\B_N_Khajiit_M_Skins.nif";
const std::string beast3 ="meshes\\b\\B_N_Argonian_F_Skins.nif";
const std::string beast4 ="meshes\\b\\B_N_Argonian_M_Skins.nif";
const std::string beasttail1 ="tail\\b\\B_N_Khajiit_F_Skins.nif";
const std::string beasttail2 ="tail\\b\\B_N_Khajiit_M_Skins.nif";
const std::string beasttail3 ="tail\\b\\B_N_Argonian_F_Skins.nif";
const std::string beasttail4 ="tail\\b\\B_N_Argonian_M_Skins.nif";
MeshPtr themesh;
if (!ptr.isNull()){
//if(pieces > 1)
//cout << "It exists\n";
resize = MeshPtr(ptr);
//resize->load();
//resize->reload();
themesh = MeshPtr(ptr);
}
else // Nope, create a new one.
{
resize = MeshManager::getSingleton().createManual(name, group, NIFLoader::getSingletonPtr());
//cout <<"EXISTING" << name << "\n";
themesh = MeshManager::getSingleton().createManual(name, group, NIFLoader::getSingletonPtr());
}
return themesh;
}
//if(pieces > 1)
//cout << "Creating it\n";
/*
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){
//resize->load();
//resize->reload();
//return 0;
ResourcePtr ptr = m->getByName(name, group);
resize = MeshPtr(ptr);
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;
//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;
}
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

@ -28,10 +28,38 @@
#include <OgreMesh.h>
#include <assert.h>
#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;
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
{
class Node;
@ -52,6 +80,7 @@ namespace Mangle
namespace NifOgre
{
/** Manual resource loader for NIF meshes. This is the main class
responsible for translating the internal NIF mesh structure into
something Ogre can use. Later it will also handle the insertion of
@ -78,23 +107,34 @@ class NIFLoader : Ogre::ManualResourceLoader
static Ogre::MeshPtr load(const std::string &name,
const std::string &group="General");
//void insertMeshInsideBase(Ogre::Mesh* mesh);
std::vector<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::Quaternion convertRotation(const Nif::Matrix& rot);
void setOutputAnimFiles(bool output);
void setVerbosePath(std::string path);
private:
NIFLoader() : resourceGroup("General") { skincounter = 0; resourceName = "";}
NIFLoader() : resourceName(""), resourceGroup("General"), flip(false), mNormaliseNormals(false),
mFlipVertexWinding(false), mOutputAnimFiles(false) {}
NIFLoader(NIFLoader& n) {}
void calculateTransform();
void warn(std::string msg);
void fail(std::string msg);
void handleNode( Nif::Node *node, int flags,
const Nif::Transformation *trafo, BoundsFinder &bounds, Ogre::Bone *parentBone);
const Nif::Transformation *trafo, BoundsFinder &bounds, Ogre::Bone *parentBone, std::vector<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);
@ -124,21 +164,34 @@ class NIFLoader : Ogre::ManualResourceLoader
// extension from .tga to .dds if the texture is missing.
Mangle::VFS::OgreVFS *vfs;
std::string verbosePath;
std::string resourceName;
std::string resourceGroup;
int skincounter;
bool isChest;
bool isBeast;
bool isHands;
bool isFeet;
int counter;
int numbers;
int stack;
Ogre::Matrix4 mTransform;
Ogre::AxisAlignedBox mBoundingBox;
bool flip;
bool mNormaliseNormals;
bool mFlipVertexWinding;
bool bNiTri;
bool mOutputAnimFiles;
std::multimap<std::string,std::string> MaterialMap;
// pointer to the ogre mesh which is currently build
Ogre::Mesh *mesh;
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…
Cancel
Save