OpenMW: create a window and render the starting cell(s)

c++11
scrawl 10 years ago
parent a0b43f426e
commit c92592493e

@ -127,8 +127,7 @@ int main(int argc, char** argv)
osg::Group* newNode = new osg::Group; osg::Group* newNode = new osg::Group;
NifOsg::Loader loader; NifOsg::Loader loader;
Resource::TextureManager texMgr(&resourceMgr); Resource::TextureManager texMgr(&resourceMgr);
loader.mTextureManager = &texMgr; newNode->addChild(loader.load(nif, &texMgr));
newNode->addChild(loader.load(nif));
osg::PositionAttitudeTransform* trans = new osg::PositionAttitudeTransform; osg::PositionAttitudeTransform* trans = new osg::PositionAttitudeTransform;
root->addChild(trans); root->addChild(trans);

@ -20,8 +20,8 @@ set(GAME_HEADER
source_group(game FILES ${GAME} ${GAME_HEADER}) source_group(game FILES ${GAME} ${GAME_HEADER})
add_openmw_dir (mwrender add_openmw_dir (mwrender
actors objects actors objects renderingmanager animation
# renderingmanager debugging sky camera animation npcanimation creatureanimation activatoranimation # debugging sky camera npcanimation creatureanimation activatoranimation
# renderinginterface localmap occlusionquery water shadows # renderinginterface localmap occlusionquery water shadows
# characterpreview globalmap ripplesimulation refraction # characterpreview globalmap ripplesimulation refraction
# terrainstorage renderconst effectmanager weaponanimation # terrainstorage renderconst effectmanager weaponanimation
@ -129,6 +129,7 @@ target_link_libraries(openmw
${OENGINE_LIBRARY} ${OENGINE_LIBRARY}
${OGRE_LIBRARIES} ${OGRE_LIBRARIES}
${OGRE_STATIC_PLUGINS} ${OGRE_STATIC_PLUGINS}
${OPENSCENEGRAPH_LIBRARIES}
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${OPENAL_LIBRARY} ${OPENAL_LIBRARY}
${SOUND_INPUT_LIBRARY} ${SOUND_INPUT_LIBRARY}

@ -3,15 +3,23 @@
#include <stdexcept> #include <stdexcept>
#include <iomanip> #include <iomanip>
#include <OgreRoot.h> #include <osgGA/TrackballManipulator>
#include <OgreRenderWindow.h> #include <osgViewer/ViewerEventHandlers>
#include <osgUtil/IncrementalCompileOperation>
#include <MyGUI_WidgetManager.h> #include <MyGUI_WidgetManager.h>
#include <SDL.h> #include <SDL.h>
// TODO: move to component
#include <openengine/misc/rng.hpp> #include <openengine/misc/rng.hpp>
#include <components/vfs/manager.hpp>
#include <components/vfs/registerarchives.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/compiler/extensions0.hpp> #include <components/compiler/extensions0.hpp>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
@ -172,8 +180,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
} }
OMW::Engine::Engine(Files::ConfigurationManager& configurationManager) OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
: mOgre (0) : mVerboseScripts (false)
, mVerboseScripts (false)
, mSkipMenu (false) , mSkipMenu (false)
, mUseSound (true) , mUseSound (true)
, mCompileAll (false) , mCompileAll (false)
@ -220,10 +227,6 @@ void OMW::Engine::addResourcesDirectory (const boost::filesystem::path& path)
{ {
} }
void OMW::Engine::addZipResource (const boost::filesystem::path& path)
{
}
void OMW::Engine::enableFSStrict(bool fsStrict) void OMW::Engine::enableFSStrict(bool fsStrict)
{ {
mFSStrict = fsStrict; mFSStrict = fsStrict;
@ -318,21 +321,27 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
addResourcesDirectory(mResDir / "shadows"); addResourcesDirectory(mResDir / "shadows");
addResourcesDirectory(mResDir / "materials"); addResourcesDirectory(mResDir / "materials");
OEngine::Render::WindowSettings windowSettings; //OEngine::Render::WindowSettings windowSettings;
windowSettings.fullscreen = settings.getBool("fullscreen", "Video"); //windowSettings.fullscreen = settings.getBool("fullscreen", "Video");
windowSettings.window_border = settings.getBool("window border", "Video"); //windowSettings.window_border = settings.getBool("window border", "Video");
windowSettings.window_x = settings.getInt("resolution x", "Video"); //windowSettings.vsync = settings.getBool("vsync", "Video");
windowSettings.window_y = settings.getInt("resolution y", "Video"); //windowSettings.icon = "openmw.png";
windowSettings.screen = settings.getInt("screen", "Video"); //std::string aa = settings.getString("antialiasing", "Video");
windowSettings.vsync = settings.getBool("vsync", "Video"); //windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0";
windowSettings.icon = "openmw.png";
std::string aa = settings.getString("antialiasing", "Video");
windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0";
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS,
settings.getBool("minimize on focus loss", "Video") ? "1" : "0"); settings.getBool("minimize on focus loss", "Video") ? "1" : "0");
//Bsa::registerResources (mFileCollections, mArchives, true, mFSStrict); // not handling fullscreen yet, we should figure this out when adding SDL to the mix
mViewer.setUpViewInWindow(0, 0, settings.getInt("resolution x", "Video"), settings.getInt("resolution y", "Video"), settings.getInt("screen", "Video"));
osg::ref_ptr<osg::Group> rootNode (new osg::Group);
mViewer.setSceneData(rootNode);
mVFS.reset(new VFS::Manager(mFSStrict));
VFS::registerArchives(mVFS.get(), mFileCollections, mArchives, true);
mResourceSystem.reset(new Resource::ResourceSystem(mVFS.get()));
// Create input and UI first to set up a bootstrapping environment for // Create input and UI first to set up a bootstrapping environment for
// showing a loading screen and keeping the window responsive while doing so // showing a loading screen and keeping the window responsive while doing so
@ -378,8 +387,8 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
} }
// Create the world // Create the world
mEnvironment.setWorld( new MWWorld::World (mFileCollections, mContentFiles, mEnvironment.setWorld( new MWWorld::World (mViewer, rootNode, mResourceSystem.get(),
mResDir, mCfgMgr.getCachePath(), mEncoder, mFallbackMap, mFileCollections, mContentFiles, mEncoder, mFallbackMap,
mActivationDistanceOverride, mCellName, mStartupScript)); mActivationDistanceOverride, mCellName, mStartupScript));
MWBase::Environment::get().getWorld()->setupPlayer(); MWBase::Environment::get().getWorld()->setupPlayer();
//input->setPlayer(&mEnvironment.getWorld()->getPlayer()); //input->setPlayer(&mEnvironment.getWorld()->getPlayer());
@ -460,7 +469,7 @@ void OMW::Engine::go()
{ {
MWBase::Environment::get().getStateManager()->loadGame(mSaveGameFile); MWBase::Environment::get().getStateManager()->loadGame(mSaveGameFile);
} }
else if (!mSkipMenu) else if (0)// !mSkipMenu)
{ {
// start in main menu // start in main menu
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
@ -481,6 +490,22 @@ void OMW::Engine::go()
} }
// Start the main rendering loop // Start the main rendering loop
mViewer.setCameraManipulator(new osgGA::TrackballManipulator);
mViewer.addEventHandler(new osgViewer::StatsHandler);
osg::Timer timer;
//osgUtil::IncrementalCompileOperation* ico = new osgUtil::IncrementalCompileOperation;
//ico->compileAllForNextFrame(1);
//mViewer.setRealizeOperation(ico);
mViewer.realize();
std::cout << "realize took " << timer.time_m() << std::endl;
while (!mViewer.done())
{
MWBase::Environment::get().getWorld()->update(0.f, false);
mViewer.frame(/*simulationTime*/);
}
/* /*
Ogre::Timer timer; Ogre::Timer timer;
while (!MWBase::Environment::get().getStateManager()->hasQuitRequest()) while (!MWBase::Environment::get().getStateManager()->hasQuitRequest())

@ -9,11 +9,23 @@
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <components/nifcache/nifcache.hpp> #include <components/nifcache/nifcache.hpp>
#include <osgViewer/Viewer>
#include "mwbase/environment.hpp" #include "mwbase/environment.hpp"
#include "mwworld/ptr.hpp" #include "mwworld/ptr.hpp"
namespace Resource
{
class ResourceSystem;
}
namespace VFS
{
class Manager;
}
namespace Compiler namespace Compiler
{ {
class Context; class Context;
@ -39,19 +51,6 @@ namespace MWGui
class WindowManager; class WindowManager;
} }
namespace OEngine
{
namespace GUI
{
class MyGUIManager;
}
namespace Render
{
class OgreRenderer;
}
}
namespace Files namespace Files
{ {
struct ConfigurationManager; struct ConfigurationManager;
@ -62,13 +61,15 @@ namespace OMW
/// \brief Main engine class, that brings together all the components of OpenMW /// \brief Main engine class, that brings together all the components of OpenMW
class Engine : private Ogre::FrameListener class Engine : private Ogre::FrameListener
{ {
std::auto_ptr<VFS::Manager> mVFS;
std::auto_ptr<Resource::ResourceSystem> mResourceSystem;
MWBase::Environment mEnvironment; MWBase::Environment mEnvironment;
ToUTF8::FromType mEncoding; ToUTF8::FromType mEncoding;
ToUTF8::Utf8Encoder* mEncoder; ToUTF8::Utf8Encoder* mEncoder;
Files::PathContainer mDataDirs; Files::PathContainer mDataDirs;
std::vector<std::string> mArchives; std::vector<std::string> mArchives;
boost::filesystem::path mResDir; boost::filesystem::path mResDir;
OEngine::Render::OgreRenderer *mOgre; osgViewer::Viewer mViewer;
std::string mCellName; std::string mCellName;
std::vector<std::string> mContentFiles; std::vector<std::string> mContentFiles;
bool mVerboseScripts; bool mVerboseScripts;
@ -108,9 +109,6 @@ namespace OMW
/// \note This function works recursively. /// \note This function works recursively.
void addResourcesDirectory (const boost::filesystem::path& path); void addResourcesDirectory (const boost::filesystem::path& path);
/// add a .zip resource
void addZipResource (const boost::filesystem::path& path);
void executeLocalScripts(); void executeLocalScripts();
virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt); virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt);

@ -16,7 +16,7 @@
#include "../mwworld/failedaction.hpp" #include "../mwworld/failedaction.hpp"
#include "../mwworld/nullaction.hpp" #include "../mwworld/nullaction.hpp"
#include "../mwrender/actors.hpp" #include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp" #include "../mwrender/renderinginterface.hpp"
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
@ -34,8 +34,7 @@ namespace MWClass
void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const
{ {
if (!model.empty()) { if (!model.empty()) {
MWRender::Actors& actors = renderingInterface.getActors(); renderingInterface.getObjects().insertModel(ptr, model, true);
actors.insertActivator(ptr, model);
} }
} }

@ -23,7 +23,7 @@
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
#include "../mwrender/actors.hpp" #include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp" #include "../mwrender/renderinginterface.hpp"
#include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/npcstats.hpp"
@ -93,8 +93,7 @@ namespace MWClass
void Container::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const void Container::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const
{ {
if (!model.empty()) { if (!model.empty()) {
MWRender::Actors& actors = renderingInterface.getActors(); renderingInterface.getObjects().insertModel(ptr, model, true);
actors.insertActivator(ptr, model);
} }
} }

@ -29,7 +29,7 @@
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwrender/renderinginterface.hpp" #include "../mwrender/renderinginterface.hpp"
#include "../mwrender/actors.hpp" #include "../mwrender/objects.hpp"
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
@ -163,10 +163,10 @@ namespace MWClass
void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const
{ {
//MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>(); MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
//MWRender::Actors& actors = renderingInterface.getActors(); MWRender::Objects& objects = renderingInterface.getObjects();
//actors.insertCreature(ptr, model, (ref->mBase->mFlags & ESM::Creature::Weapon) != 0); objects.insertCreature(ptr, model, (ref->mBase->mFlags & ESM::Creature::Weapon) != 0);
} }
void Creature::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWWorld::PhysicsSystem& physics) const void Creature::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWWorld::PhysicsSystem& physics) const

@ -24,7 +24,7 @@
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
#include "../mwrender/actors.hpp" #include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp" #include "../mwrender/renderinginterface.hpp"
namespace namespace
@ -52,8 +52,7 @@ namespace MWClass
void Door::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const void Door::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const
{ {
if (!model.empty()) { if (!model.empty()) {
MWRender::Actors& actors = renderingInterface.getActors(); renderingInterface.getObjects().insertModel(ptr, model, true);
actors.insertActivator(ptr, model);
} }
} }

@ -23,7 +23,6 @@
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwrender/actors.hpp"
#include "../mwrender/renderinginterface.hpp" #include "../mwrender/renderinginterface.hpp"
namespace MWClass namespace MWClass
@ -39,8 +38,7 @@ namespace MWClass
ptr.get<ESM::Light>(); ptr.get<ESM::Light>();
// Insert even if model is empty, so that the light is added // Insert even if model is empty, so that the light is added
MWRender::Actors& actors = renderingInterface.getActors(); renderingInterface.getObjects().insertModel(ptr, model, true, !(ref->mBase->mData.mFlags & ESM::Light::OffDefault));
actors.insertActivator(ptr, model, !(ref->mBase->mData.mFlags & ESM::Light::OffDefault));
} }
void Light::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWWorld::PhysicsSystem& physics) const void Light::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWWorld::PhysicsSystem& physics) const

@ -35,7 +35,7 @@
#include "../mwworld/physicssystem.hpp" #include "../mwworld/physicssystem.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwrender/actors.hpp" #include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp" #include "../mwrender/renderinginterface.hpp"
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
@ -409,7 +409,7 @@ namespace MWClass
void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const
{ {
renderingInterface.getActors().insertNPC(ptr); renderingInterface.getObjects().insertNPC(ptr);
} }
void Npc::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWWorld::PhysicsSystem& physics) const void Npc::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWWorld::PhysicsSystem& physics) const

@ -1702,6 +1702,7 @@ namespace MWGui
void WindowManager::playVideo(const std::string &name, bool allowSkipping) void WindowManager::playVideo(const std::string &name, bool allowSkipping)
{ {
return;
mVideoWidget->playVideo("video\\" + name); mVideoWidget->playVideo("video\\" + name);
mVideoWidget->eventKeyButtonPressed.clear(); mVideoWidget->eventKeyButtonPressed.clear();

@ -474,7 +474,7 @@ namespace MWMechanics
Ogre::Vector3 dir = playerPos - actorPos; Ogre::Vector3 dir = playerPos - actorPos;
Ogre::Radian faceAngle = Ogre::Math::ATan2(dir.x,dir.y); Ogre::Radian faceAngle = Ogre::Math::ATan2(dir.x,dir.y);
Ogre::Radian actorAngle = actor.getRefData().getBaseNode()->getOrientation().getRoll(); Ogre::Radian actorAngle = actor.getRefData().getBaseNodeOld()->getOrientation().getRoll();
// an attempt at reducing the turning animation glitch // an attempt at reducing the turning animation glitch
if( Ogre::Math::Abs( faceAngle - actorAngle ) >= Ogre::Degree(5) ) // TODO: is there a better way? if( Ogre::Math::Abs( faceAngle - actorAngle ) >= Ogre::Degree(5) ) // TODO: is there a better way?
{ {

@ -75,7 +75,7 @@ namespace MWMechanics
return false; return false;
Ogre::Degree angle = signedAngle (Ogre::Vector3(attacker.getRefData().getPosition().pos) - Ogre::Vector3(blocker.getRefData().getPosition().pos), Ogre::Degree angle = signedAngle (Ogre::Vector3(attacker.getRefData().getPosition().pos) - Ogre::Vector3(blocker.getRefData().getPosition().pos),
blocker.getRefData().getBaseNode()->getOrientation().yAxis(), Ogre::Vector3(0,0,1)); blocker.getRefData().getBaseNodeOld()->getOrientation().yAxis(), Ogre::Vector3(0,0,1));
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
if (angle.valueDegrees() < gmst.find("fCombatBlockLeftAngle")->getFloat()) if (angle.valueDegrees() < gmst.find("fCombatBlockLeftAngle")->getFloat())

@ -3,6 +3,8 @@
#include <openengine/misc/rng.hpp> #include <openengine/misc/rng.hpp>
#include <iostream>
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "../mwworld/manualref.hpp" #include "../mwworld/manualref.hpp"

@ -1385,7 +1385,7 @@ namespace MWMechanics
static float fSneakViewMult = store.find("fSneakViewMult")->getFloat(); static float fSneakViewMult = store.find("fSneakViewMult")->getFloat();
float y = 0; float y = 0;
Ogre::Vector3 vec = pos1 - pos2; Ogre::Vector3 vec = pos1 - pos2;
Ogre::Radian angle = observer.getRefData().getBaseNode()->getOrientation().yAxis().angleBetween(vec); Ogre::Radian angle = observer.getRefData().getBaseNodeOld()->getOrientation().yAxis().angleBetween(vec);
if (angle < Ogre::Degree(90)) if (angle < Ogre::Degree(90))
y = obsTerm * observerStats.getFatigueTerm() * fSneakNoViewMult; y = obsTerm * observerStats.getFatigueTerm() * fSneakNoViewMult;
else else

@ -418,7 +418,7 @@ namespace MWMechanics
absorbed = (OEngine::Misc::Rng::roll0to99() < absorb); absorbed = (OEngine::Misc::Rng::roll0to99() < absorb);
if (absorbed) if (absorbed)
{ {
const ESM::Static* absorbStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_Absorb"); //const ESM::Static* absorbStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_Absorb");
//MWBase::Environment::get().getWorld()->getAnimation(target)->addEffect( //MWBase::Environment::get().getWorld()->getAnimation(target)->addEffect(
// "meshes\\" + absorbStatic->mModel, ESM::MagicEffect::SpellAbsorption, false, ""); // "meshes\\" + absorbStatic->mModel, ESM::MagicEffect::SpellAbsorption, false, "");
// Magicka is increased by cost of spell // Magicka is increased by cost of spell
@ -466,7 +466,7 @@ namespace MWMechanics
bool isReflected = (OEngine::Misc::Rng::roll0to99() < reflect); bool isReflected = (OEngine::Misc::Rng::roll0to99() < reflect);
if (isReflected) if (isReflected)
{ {
const ESM::Static* reflectStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_Reflect"); //const ESM::Static* reflectStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_Reflect");
//MWBase::Environment::get().getWorld()->getAnimation(target)->addEffect( //MWBase::Environment::get().getWorld()->getAnimation(target)->addEffect(
// "meshes\\" + reflectStatic->mModel, ESM::MagicEffect::Reflect, false, ""); // "meshes\\" + reflectStatic->mModel, ESM::MagicEffect::Reflect, false, "");
reflectedEffects.mList.push_back(*effectIt); reflectedEffects.mList.push_back(*effectIt);
@ -565,7 +565,7 @@ namespace MWMechanics
} }
// Add VFX // Add VFX
const ESM::Static* castStatic; /*const ESM::Static* castStatic;
if (!magicEffect->mHit.empty()) if (!magicEffect->mHit.empty())
castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find (magicEffect->mHit); castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find (magicEffect->mHit);
else else
@ -574,9 +574,10 @@ namespace MWMechanics
// TODO: VFX are no longer active after saving/reloading the game // TODO: VFX are no longer active after saving/reloading the game
bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0; bool loop = (magicEffect->mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0;
// Note: in case of non actor, a free effect should be fine as well // Note: in case of non actor, a free effect should be fine as well
//MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(target); MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(target);
//if (anim) if (anim)
// anim->addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, ""); anim->addEffect("meshes\\" + castStatic->mModel, magicEffect->mIndex, loop, "");
*/
} }
} }
} }

@ -1,8 +1,6 @@
#ifndef GAME_RENDER_ACTORS_H #ifndef GAME_RENDER_ACTORS_H
#define GAME_RENDER_ACTORS_H #define GAME_RENDER_ACTORS_H
//#include <openengine/ogre/renderer.hpp>
#include <string> #include <string>
namespace OEngine namespace OEngine

File diff suppressed because it is too large Load Diff

@ -4,15 +4,20 @@
#include <OgreController.h> #include <OgreController.h>
#include <OgreVector3.h> #include <OgreVector3.h>
#include <components/nifogre/ogrenifloader.hpp>
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include <components/nifosg/controller.hpp>
namespace ESM namespace ESM
{ {
struct Light; struct Light;
} }
namespace Resource
{
class ResourceSystem;
}
namespace MWRender namespace MWRender
{ {
class Camera; class Camera;
@ -69,20 +74,18 @@ protected:
virtual void setValue(Ogre::Real value); virtual void setValue(Ogre::Real value);
}; };
class NullAnimationTime : public NifOsg::ControllerSource
class NullAnimationTime : public Ogre::ControllerValue<Ogre::Real>
{ {
public: public:
virtual Ogre::Real getValue() const virtual float getValue(osg::NodeVisitor *nv)
{ return 0.0f; } {
virtual void setValue(Ogre::Real value) return 0.f;
{ } }
}; };
struct AnimSource : public Ogre::AnimationAlloc { struct AnimSource : public Ogre::AnimationAlloc {
NifOgre::TextKeyMap mTextKeys; //NifOgre::TextKeyMap mTextKeys;
std::vector<Ogre::Controller<Ogre::Real> > mControllers[sNumGroups]; std::vector<Ogre::Controller<Ogre::Real> > mControllers[sNumGroups];
}; };
typedef std::vector< Ogre::SharedPtr<AnimSource> > AnimSourceList; typedef std::vector< Ogre::SharedPtr<AnimSource> > AnimSourceList;
@ -113,106 +116,71 @@ protected:
typedef std::map<Ogre::MovableObject*,std::string> ObjectAttachMap; typedef std::map<Ogre::MovableObject*,std::string> ObjectAttachMap;
struct EffectParams osg::ref_ptr<osg::Group> mInsert;
{
std::string mModelName; // Just here so we don't add the same effect twice
NifOgre::ObjectScenePtr mObjects;
int mEffectId;
bool mLoop;
std::string mBoneName;
};
std::vector<EffectParams> mEffects; osg::ref_ptr<osg::Node> mObjectRoot;
MWWorld::Ptr mPtr; MWWorld::Ptr mPtr;
Ogre::Light* mGlowLight; Resource::ResourceSystem* mResourceSystem;
Ogre::SceneNode *mInsert;
Ogre::Entity *mSkelBase;
NifOgre::ObjectScenePtr mObjectRoot;
AnimSourceList mAnimSources;
Ogre::Node *mAccumRoot;
Ogre::Node *mNonAccumRoot;
NifOgre::NodeTargetValue<Ogre::Real> *mNonAccumCtrl;
Ogre::Vector3 mAccumulate;
AnimStateMap mStates;
Ogre::SharedPtr<AnimationTime> mAnimationTimePtr[sNumGroups];
Ogre::SharedPtr<NullAnimationTime> mNullAnimationTimePtr;
ObjectAttachMap mAttachedObjects;
/* Sets the appropriate animations on the bone groups based on priority. /* Sets the appropriate animations on the bone groups based on priority.
*/ */
void resetActiveGroups(); //void resetActiveGroups();
static size_t detectAnimGroup(const Ogre::Node *node); //static size_t detectAnimGroup(const Ogre::Node *node);
/*
static float calcAnimVelocity(const NifOgre::TextKeyMap &keys, static float calcAnimVelocity(const NifOgre::TextKeyMap &keys,
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl, NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl,
const Ogre::Vector3 &accum, const Ogre::Vector3 &accum,
const std::string &groupname); const std::string &groupname);
*/
/* Updates a skeleton instance so that all bones matching the source skeleton (based on
* bone names) are positioned identically. */
void updateSkeletonInstance(const Ogre::SkeletonInstance *skelsrc, Ogre::SkeletonInstance *skel);
/* Updates the position of the accum root node for the given time, and /* Updates the position of the accum root node for the given time, and
* returns the wanted movement vector from the previous time. */ * returns the wanted movement vector from the previous time. */
void updatePosition(float oldtime, float newtime, Ogre::Vector3 &position); //void updatePosition(float oldtime, float newtime, Ogre::Vector3 &position);
static NifOgre::TextKeyMap::const_iterator findGroupStart(const NifOgre::TextKeyMap &keys, const std::string &groupname); //static NifOgre::TextKeyMap::const_iterator findGroupStart(const NifOgre::TextKeyMap &keys, const std::string &groupname);
/* Resets the animation to the time of the specified start marker, without /* Resets the animation to the time of the specified start marker, without
* moving anything, and set the end time to the specified stop marker. If * moving anything, and set the end time to the specified stop marker. If
* the marker is not found, or if the markers are the same, it returns * the marker is not found, or if the markers are the same, it returns
* false. * false.
*/ */
bool reset(AnimState &state, const NifOgre::TextKeyMap &keys, //bool reset(AnimState &state, const NifOgre::TextKeyMap &keys,
const std::string &groupname, const std::string &start, const std::string &stop, // const std::string &groupname, const std::string &start, const std::string &stop,
float startpoint, bool loopfallback); // float startpoint, bool loopfallback);
void handleTextKey(AnimState &state, const std::string &groupname, const NifOgre::TextKeyMap::const_iterator &key, //void handleTextKey(AnimState &state, const std::string &groupname, const NifOgre::TextKeyMap::const_iterator &key,
const NifOgre::TextKeyMap& map); // const NifOgre::TextKeyMap& map);
/* Sets the root model of the object. If 'baseonly' is true, then any meshes or particle /* Sets the root model of the object.
* systems in the model are ignored (useful for NPCs, where only the skeleton is needed for
* the root).
* *
* Note that you must make sure all animation sources are cleared before reseting the object * Note that you must make sure all animation sources are cleared before reseting the object
* root. All nodes previously retrieved with getNode will also become invalidated. * root. All nodes previously retrieved with getNode will also become invalidated.
*/ */
void setObjectRoot(const std::string &model, bool baseonly); void setObjectRoot(const std::string &model);
/* Adds the keyframe controllers in the specified model as a new animation source. Note that /* Adds the keyframe controllers in the specified model as a new animation source. Note that
* the filename portion of the provided model name will be prepended with 'x', and the .nif * the filename portion of the provided model name will be prepended with 'x', and the .nif
* extension will be replaced with .kf. */ * extension will be replaced with .kf. */
void addAnimSource(const std::string &model); //void addAnimSource(const std::string &model);
/** Adds an additional light to the given object list using the specified ESM record. */ /** Adds an additional light to the given object list using the specified ESM record. */
void addExtraLight(Ogre::SceneManager *sceneMgr, NifOgre::ObjectScenePtr objlist, const ESM::Light *light); //void addExtraLight(Ogre::SceneManager *sceneMgr, NifOgre::ObjectScenePtr objlist, const ESM::Light *light);
void clearAnimSources();
// TODO: Should not be here //void clearAnimSources();
Ogre::Vector3 getEnchantmentColor(MWWorld::Ptr item);
public: public:
// FIXME: Move outside of this class
static void setRenderProperties(NifOgre::ObjectScenePtr objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue,
Ogre::uint8 transqueue, Ogre::Real dist=0.0f,
bool enchantedGlow=false, Ogre::Vector3* glowColor=NULL);
/// Returns the name of the .nif file that makes up this animation's base skeleton. Animation(const MWWorld::Ptr &ptr, osg::ref_ptr<osg::Group> node, Resource::ResourceSystem* resourceSystem);
/// If there is no skeleton, returns "".
std::string getObjectRootName() const;
Animation(const MWWorld::Ptr &ptr, Ogre::SceneNode *node);
virtual ~Animation(); virtual ~Animation();
osg::Group* getOrCreateObjectRoot();
osg::Group* getObjectRoot();
/** /**
* @brief Add an effect mesh attached to a bone or the insert scene node * @brief Add an effect mesh attached to a bone or the insert scene node
* @param model * @param model
@ -223,25 +191,18 @@ public:
* @param texture override the texture specified in the model's materials * @param texture override the texture specified in the model's materials
* @note Will not add an effect twice. * @note Will not add an effect twice.
*/ */
void addEffect (const std::string& model, int effectId, bool loop = false, const std::string& bonename = "", std::string texture = ""); //void addEffect (const std::string& model, int effectId, bool loop = false, const std::string& bonename = "", std::string texture = "");
void removeEffect (int effectId); //void removeEffect (int effectId);
void getLoopingEffects (std::vector<int>& out); //void getLoopingEffects (std::vector<int>& out);
/// Prepare this animation for being rendered with \a camera (rotates billboard nodes) //void updatePtr(const MWWorld::Ptr &ptr);
virtual void preRender (Ogre::Camera* camera);
virtual void setAlpha(float alpha) {} //bool hasAnimation(const std::string &anim);
virtual void setVampire(bool vampire) {}
public:
void updatePtr(const MWWorld::Ptr &ptr);
bool hasAnimation(const std::string &anim);
// Specifies the axis' to accumulate on. Non-accumulated axis will just // Specifies the axis' to accumulate on. Non-accumulated axis will just
// move visually, but not affect the actual movement. Each x/y/z value // move visually, but not affect the actual movement. Each x/y/z value
// should be on the scale of 0 to 1. // should be on the scale of 0 to 1.
void setAccumulation(const Ogre::Vector3 &accum); //void setAccumulation(const Ogre::Vector3 &accum);
/** Plays an animation. /** Plays an animation.
* \param groupname Name of the animation group to play. * \param groupname Name of the animation group to play.
@ -263,23 +224,23 @@ public:
* \param loopFallback Allow looping an animation that has no loop keys, i.e. fall back to use * \param loopFallback Allow looping an animation that has no loop keys, i.e. fall back to use
* the "start" and "stop" keys for looping? * the "start" and "stop" keys for looping?
*/ */
void play(const std::string &groupname, int priority, int groups, bool autodisable, //void play(const std::string &groupname, int priority, int groups, bool autodisable,
float speedmult, const std::string &start, const std::string &stop, // float speedmult, const std::string &start, const std::string &stop,
float startpoint, size_t loops, bool loopfallback=false); // float startpoint, size_t loops, bool loopfallback=false);
/** If the given animation group is currently playing, set its remaining loop count to '0'. /** If the given animation group is currently playing, set its remaining loop count to '0'.
*/ */
void stopLooping(const std::string& groupName); //void stopLooping(const std::string& groupName);
/** Adjust the speed multiplier of an already playing animation. /** Adjust the speed multiplier of an already playing animation.
*/ */
void adjustSpeedMult (const std::string& groupname, float speedmult); //void adjustSpeedMult (const std::string& groupname, float speedmult);
/** Returns true if the named animation group is playing. */ /** Returns true if the named animation group is playing. */
bool isPlaying(const std::string &groupname) const; //bool isPlaying(const std::string &groupname) const;
/// Returns true if no important animations are currently playing on the upper body. /// Returns true if no important animations are currently playing on the upper body.
bool upperBodyReady() const; //bool upperBodyReady() const;
/** Gets info about the given animation group. /** Gets info about the given animation group.
* \param groupname Animation group to check. * \param groupname Animation group to check.
@ -287,71 +248,32 @@ public:
* \param speedmult Stores the animation speed multiplier * \param speedmult Stores the animation speed multiplier
* \return True if the animation is active, false otherwise. * \return True if the animation is active, false otherwise.
*/ */
bool getInfo(const std::string &groupname, float *complete=NULL, float *speedmult=NULL) const; //bool getInfo(const std::string &groupname, float *complete=NULL, float *speedmult=NULL) const;
/// Get the absolute position in the animation track of the first text key with the given group. /// Get the absolute position in the animation track of the first text key with the given group.
float getStartTime(const std::string &groupname) const; //float getStartTime(const std::string &groupname) const;
/// Get the absolute position in the animation track of the text key /// Get the absolute position in the animation track of the text key
float getTextKeyTime(const std::string &textKey) const; //float getTextKeyTime(const std::string &textKey) const;
/// Get the current absolute position in the animation track for the animation that is currently playing from the given group. /// Get the current absolute position in the animation track for the animation that is currently playing from the given group.
float getCurrentTime(const std::string& groupname) const; //float getCurrentTime(const std::string& groupname) const;
/** Disables the specified animation group; /** Disables the specified animation group;
* \param groupname Animation group to disable. * \param groupname Animation group to disable.
*/ */
void disable(const std::string &groupname); //void disable(const std::string &groupname);
void changeGroups(const std::string &groupname, int group); //void changeGroups(const std::string &groupname, int group);
virtual void setWeaponGroup(const std::string& group) {}
/** Retrieves the velocity (in units per second) that the animation will move. */ /** Retrieves the velocity (in units per second) that the animation will move. */
float getVelocity(const std::string &groupname) const; //float getVelocity(const std::string &groupname) const;
/// A relative factor (0-1) that decides if and how much the skeleton should be pitched virtual osg::Vec3f runAnimation(float duration);
/// to indicate the facing orientation of the character.
virtual void setPitchFactor(float factor) {}
virtual void setHeadPitch(Ogre::Radian factor) {}
virtual void setHeadYaw(Ogre::Radian factor) {}
virtual Ogre::Radian getHeadPitch() const { return Ogre::Radian(0.f); }
virtual Ogre::Radian getHeadYaw() const { return Ogre::Radian(0.f); }
virtual Ogre::Vector3 runAnimation(float duration);
/// This is typically called as part of runAnimation, but may be called manually if needed.
void updateEffects(float duration);
// TODO: move outside of this class
/// Makes this object glow, by placing a Light in its center.
/// @param effect Controls the radius and intensity of the light.
void setLightEffect(float effect);
virtual void showWeapons(bool showWeapon);
virtual void showCarriedLeft(bool show) {}
virtual void attachArrow() {}
virtual void releaseArrow() {}
void enableLights(bool enable);
virtual void enableHeadAnimation(bool enable) {}
Ogre::AxisAlignedBox getWorldBounds();
Ogre::Node *getNode(const std::string &name);
Ogre::Node *getNode(int handle);
// Attaches the given object to a bone on this object's base skeleton. If the bone doesn't
// exist, the object isn't attached and NULL is returned. The returned TagPoint is only
// valid until the next setObjectRoot call.
Ogre::TagPoint *attachObjectToBone(const Ogre::String &bonename, Ogre::MovableObject *obj);
void detachObjectFromBone(Ogre::MovableObject *obj);
}; };
class ObjectAnimation : public Animation { class ObjectAnimation : public Animation {
public: public:
ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model); ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model, Resource::ResourceSystem* resourceSystem);
bool canBatch() const;
void fillBatch(Ogre::StaticGeometry *sg);
}; };
} }

@ -2,110 +2,204 @@
#include <cmath> #include <cmath>
#include <OgreSceneNode.h> #include <osg/io_utils>
#include <OgreSceneManager.h> #include <osg/Group>
#include <OgreEntity.h> #include <osg/Geode>
#include <OgreLight.h> #include <osg/PositionAttitudeTransform>
#include <OgreSubEntity.h> #include <osg/ComputeBoundsVisitor>
#include <OgreParticleSystem.h>
#include <OgreParticleEmitter.h>
#include <OgreStaticGeometry.h>
#include <components/esm/loadligh.hpp> #include <osgParticle/ParticleSystem>
#include <components/esm/loadstat.hpp> #include <osgParticle/ParticleProcessor>
//#include <components/nifogre/ogrenifloader.hpp> // light
#include <components/settings/settings.hpp> #include <components/sceneutil/lightmanager.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/visitor.hpp>
#include <components/sceneutil/util.hpp>
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "renderconst.hpp" #include "renderconst.hpp"
//#include "animation.hpp" #include "animation.hpp"
namespace
{
/// Removes all particle systems and related nodes in a subgraph.
class RemoveParticlesVisitor : public osg::NodeVisitor
{
public:
RemoveParticlesVisitor()
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
{ }
virtual void apply(osg::Node &node)
{
if (dynamic_cast<osgParticle::ParticleSystem*>(&node) || dynamic_cast<osgParticle::ParticleProcessor*>(&node))
mToRemove.push_back(&node);
traverse(node);
}
using namespace MWRender; void remove()
{
for (std::vector<osg::ref_ptr<osg::Node> >::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
{
osg::Node* node = *it;
if (node->getNumParents())
node->getParent(0)->removeChild(node);
}
mToRemove.clear();
}
int Objects::uniqueID = 0; private:
std::vector<osg::ref_ptr<osg::Node> > mToRemove;
};
}
void Objects::setRootNode(Ogre::SceneNode* root)
namespace MWRender
{
Objects::Objects(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> rootNode)
: mResourceSystem(resourceSystem)
, mRootNode(rootNode)
{ {
mRootNode = root; }
Objects::~Objects()
{
for(PtrAnimationMap::iterator iter = mObjects.begin();iter != mObjects.end();++iter)
delete iter->second;
mObjects.clear();
for (CellMap::iterator iter = mCellSceneNodes.begin(); iter != mCellSceneNodes.end(); ++iter)
iter->second->getParent(0)->removeChild(iter->second);
mCellSceneNodes.clear();
} }
void Objects::insertBegin(const MWWorld::Ptr& ptr) void Objects::insertBegin(const MWWorld::Ptr& ptr)
{ {
Ogre::SceneNode* root = mRootNode; osg::ref_ptr<osg::Group> cellnode;
Ogre::SceneNode* cellnode;
if(mCellSceneNodes.find(ptr.getCell()) == mCellSceneNodes.end()) CellMap::iterator found = mCellSceneNodes.find(ptr.getCell());
if (found == mCellSceneNodes.end())
{ {
//Create the scenenode and put it in the map cellnode = new osg::Group;
cellnode = root->createChildSceneNode(); mRootNode->addChild(cellnode);
mCellSceneNodes[ptr.getCell()] = cellnode; mCellSceneNodes[ptr.getCell()] = cellnode;
} }
else else
{ cellnode = found->second;
cellnode = mCellSceneNodes[ptr.getCell()];
}
Ogre::SceneNode* insert = cellnode->createChildSceneNode(); osg::ref_ptr<osg::PositionAttitudeTransform> insert (new osg::PositionAttitudeTransform);
const float *f = ptr.getRefData().getPosition().pos; cellnode->addChild(insert);
insert->setPosition(f[0], f[1], f[2]); const float *f = ptr.getRefData().getPosition().pos;
insert->setScale(ptr.getCellRef().getScale(), ptr.getCellRef().getScale(), ptr.getCellRef().getScale());
insert->setPosition(osg::Vec3(f[0], f[1], f[2]));
insert->setScale(osg::Vec3(ptr.getCellRef().getScale(), ptr.getCellRef().getScale(), ptr.getCellRef().getScale()));
// Convert MW rotation to a quaternion: // Convert MW rotation to a quaternion:
f = ptr.getCellRef().getPosition().rot; f = ptr.getCellRef().getPosition().rot;
// Rotate around X axis // Rotate around X axis
Ogre::Quaternion xr(Ogre::Radian(-f[0]), Ogre::Vector3::UNIT_X); osg::Quat xr(-f[0], osg::Vec3(1,0,0));
// Rotate around Y axis // Rotate around Y axis
Ogre::Quaternion yr(Ogre::Radian(-f[1]), Ogre::Vector3::UNIT_Y); osg::Quat yr(-f[1], osg::Vec3(0,1,0));
// Rotate around Z axis // Rotate around Z axis
Ogre::Quaternion zr(Ogre::Radian(-f[2]), Ogre::Vector3::UNIT_Z); osg::Quat zr(-f[2], osg::Vec3(0,0,1));
// Rotates first around z, then y, then x // Rotates first around z, then y, then x
insert->setOrientation(xr*yr*zr); insert->setAttitude(zr*yr*xr);
// TODO: actors rotate around z only
ptr.getRefData().setBaseNode(insert); ptr.getRefData().setBaseNode(insert);
} }
void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh, bool batch) void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh, bool animated, bool allowLight)
{ {
insertBegin(ptr); insertBegin(ptr);
/*
std::auto_ptr<ObjectAnimation> anim(new ObjectAnimation(ptr, mesh));
if (!mesh.empty()) std::auto_ptr<ObjectAnimation> anim (new ObjectAnimation(ptr, mesh, mResourceSystem));
if (ptr.getTypeName() == typeid(ESM::Light).name() && allowLight)
{ {
Ogre::AxisAlignedBox bounds = anim->getWorldBounds(); SceneUtil::FindByNameVisitor visitor("AttachLight");
Ogre::Vector3 extents = bounds.getSize(); ptr.getRefData().getBaseNode()->accept(visitor);
extents *= ptr.getRefData().getBaseNode()->getScale();
float size = std::max(std::max(extents.x, extents.y), extents.z); osg::Vec3f lightOffset (0.f, 0.f, 0.f);
osg::Group* attachTo = NULL;
if (visitor.mFoundNode)
{
attachTo = visitor.mFoundNode;
}
else
{
osg::ComputeBoundsVisitor computeBound;
osg::Group* objectRoot = anim->getOrCreateObjectRoot();
objectRoot->accept(computeBound);
bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && lightOffset = computeBound.getBoundingBox().center();
Settings::Manager::getBool("limit small object distance", "Viewing distance");
// do not fade out doors. that will cause holes and look stupid
if(ptr.getTypeName().find("Door") != std::string::npos)
small = false;
if (mBounds.find(ptr.getCell()) == mBounds.end()) attachTo = objectRoot;
mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL; }
mBounds[ptr.getCell()].merge(bounds);
const ESM::Light* esmLight = ptr.get<ESM::Light>()->mBase;
osg::ref_ptr<SceneUtil::LightSource> lightSource = new SceneUtil::LightSource;
osg::Light* light = new osg::Light;
lightSource->setLight(light);
light->setPosition(osg::Vec4f(lightOffset.x(), lightOffset.y(), lightOffset.z(), 1.f));
float realRadius = esmLight->mData.mRadius * 2;
lightSource->setRadius(realRadius);
light->setLinearAttenuation(10.f/realRadius);
//light->setLinearAttenuation(0.05);
light->setConstantAttenuation(0.f);
light->setDiffuse(SceneUtil::colourFromRGB(esmLight->mData.mColor));
light->setAmbient(osg::Vec4f(0,0,0,1));
light->setSpecular(osg::Vec4f(0,0,0,0));
attachTo->addChild(lightSource);
}
if (!allowLight)
{
RemoveParticlesVisitor visitor;
anim->getObjectRoot()->accept(visitor);
visitor.remove();
} }
if(anim.get() != NULL) mObjects.insert(std::make_pair(ptr, anim.release()));
mObjects.insert(std::make_pair(ptr, anim.release())); }
*/
void Objects::insertCreature(const MWWorld::Ptr &ptr, const std::string &mesh, bool weaponsShields)
{
insertBegin(ptr);
// CreatureAnimation
std::auto_ptr<ObjectAnimation> anim (new ObjectAnimation(ptr, mesh, mResourceSystem));
mObjects.insert(std::make_pair(ptr, anim.release()));
}
void Objects::insertNPC(const MWWorld::Ptr &ptr)
{
} }
bool Objects::deleteObject (const MWWorld::Ptr& ptr) bool Objects::deleteObject (const MWWorld::Ptr& ptr)
{ {
/*
if(!ptr.getRefData().getBaseNode()) if(!ptr.getRefData().getBaseNode())
return true; return true;
@ -115,18 +209,16 @@ bool Objects::deleteObject (const MWWorld::Ptr& ptr)
delete iter->second; delete iter->second;
mObjects.erase(iter); mObjects.erase(iter);
mRenderer.getScene()->destroySceneNode(ptr.getRefData().getBaseNode()); ptr.getRefData().getBaseNode()->getParent(0)->removeChild(ptr.getRefData().getBaseNode());
ptr.getRefData().setBaseNode(0); ptr.getRefData().setBaseNode(NULL);
return true; return true;
} }
*/
return false; return false;
} }
void Objects::removeCell(MWWorld::CellStore* store) void Objects::removeCell(const MWWorld::CellStore* store)
{ {
/*
for(PtrAnimationMap::iterator iter = mObjects.begin();iter != mObjects.end();) for(PtrAnimationMap::iterator iter = mObjects.begin();iter != mObjects.end();)
{ {
if(iter->first.getCell() == store) if(iter->first.getCell() == store)
@ -138,46 +230,19 @@ void Objects::removeCell(MWWorld::CellStore* store)
++iter; ++iter;
} }
std::map<MWWorld::CellStore*,Ogre::StaticGeometry*>::iterator geom = mStaticGeometry.find(store); CellMap::iterator cell = mCellSceneNodes.find(store);
if(geom != mStaticGeometry.end())
{
Ogre::StaticGeometry *sg = geom->second;
mStaticGeometry.erase(geom);
mRenderer.getScene()->destroyStaticGeometry(sg);
}
geom = mStaticGeometrySmall.find(store);
if(geom != mStaticGeometrySmall.end())
{
Ogre::StaticGeometry *sg = geom->second;
mStaticGeometrySmall.erase(store);
mRenderer.getScene()->destroyStaticGeometry(sg);
}
mBounds.erase(store);
std::map<MWWorld::CellStore*,Ogre::SceneNode*>::iterator cell = mCellSceneNodes.find(store);
if(cell != mCellSceneNodes.end()) if(cell != mCellSceneNodes.end())
{ {
cell->second->removeAndDestroyAllChildren(); cell->second->getParent(0)->removeChild(cell->second);
mRenderer.getScene()->destroySceneNode(cell->second);
mCellSceneNodes.erase(cell); mCellSceneNodes.erase(cell);
} }
*/
}
Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::CellStore* cell)
{
return mBounds[cell];
} }
void Objects::update(float dt, Ogre::Camera* camera) void Objects::update(float dt, Ogre::Camera* camera)
{ {
/*
PtrAnimationMap::const_iterator it = mObjects.begin(); PtrAnimationMap::const_iterator it = mObjects.begin();
for(;it != mObjects.end();++it) for(;it != mObjects.end();++it)
it->second->runAnimation(dt); it->second->runAnimation(dt);
*/
} }
void Objects::updateObjectCell(const MWWorld::Ptr &old, const MWWorld::Ptr &cur) void Objects::updateObjectCell(const MWWorld::Ptr &old, const MWWorld::Ptr &cur)
@ -206,13 +271,13 @@ void Objects::updateObjectCell(const MWWorld::Ptr &old, const MWWorld::Ptr &cur)
*/ */
} }
ObjectAnimation* Objects::getAnimation(const MWWorld::Ptr &ptr) Animation* Objects::getAnimation(const MWWorld::Ptr &ptr)
{ {
/*
PtrAnimationMap::const_iterator iter = mObjects.find(ptr); PtrAnimationMap::const_iterator iter = mObjects.find(ptr);
if(iter != mObjects.end()) if(iter != mObjects.end())
return iter->second; return iter->second;
*/
return NULL; return NULL;
} }
}

@ -1,10 +1,16 @@
#ifndef GAME_RENDER_OBJECTS_H #ifndef GAME_RENDER_OBJECTS_H
#define GAME_RENDER_OBJECTS_H #define GAME_RENDER_OBJECTS_H
#include <OgreColourValue.h>
#include <OgreAxisAlignedBox.h> #include <OgreAxisAlignedBox.h>
#include <openengine/ogre/renderer.hpp> #include <components/resource/resourcesystem.hpp>
#include <osg/ref_ptr>
namespace osg
{
class Group;
}
namespace MWWorld namespace MWWorld
{ {
@ -14,53 +20,52 @@ namespace MWWorld
namespace MWRender{ namespace MWRender{
class ObjectAnimation; class Animation;
class Objects{
typedef std::map<MWWorld::Ptr,ObjectAnimation*> PtrAnimationMap;
OEngine::Render::OgreRenderer &mRenderer; class Objects{
typedef std::map<MWWorld::Ptr,Animation*> PtrAnimationMap;
std::map<MWWorld::CellStore*,Ogre::SceneNode*> mCellSceneNodes; typedef std::map<const MWWorld::CellStore*, osg::ref_ptr<osg::Group> > CellMap;
std::map<MWWorld::CellStore*,Ogre::StaticGeometry*> mStaticGeometry; CellMap mCellSceneNodes;
std::map<MWWorld::CellStore*,Ogre::StaticGeometry*> mStaticGeometrySmall;
std::map<MWWorld::CellStore*,Ogre::AxisAlignedBox> mBounds;
PtrAnimationMap mObjects; PtrAnimationMap mObjects;
Ogre::SceneNode* mRootNode; osg::ref_ptr<osg::Group> mRootNode;
static int uniqueID;
void insertBegin(const MWWorld::Ptr& ptr); void insertBegin(const MWWorld::Ptr& ptr);
Resource::ResourceSystem* mResourceSystem;
public: public:
Objects(OEngine::Render::OgreRenderer &renderer) Objects(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> rootNode);
: mRenderer(renderer) ~Objects();
, mRootNode(NULL)
{} /// @param animated Attempt to load separate keyframes from a .kf file matching the model file?
~Objects(){} /// @param allowLight If false, no lights will be created, and particles systems will be cleared then frozen.
void insertModel(const MWWorld::Ptr& ptr, const std::string &model, bool batch=false); void insertModel(const MWWorld::Ptr& ptr, const std::string &model, bool animated=false, bool allowLight=true);
ObjectAnimation* getAnimation(const MWWorld::Ptr &ptr); void insertNPC(const MWWorld::Ptr& ptr);
void insertCreature (const MWWorld::Ptr& ptr, const std::string& model, bool weaponsShields);
Animation* getAnimation(const MWWorld::Ptr &ptr);
void update (float dt, Ogre::Camera* camera); void update (float dt, Ogre::Camera* camera);
///< per-frame update ///< per-frame update
Ogre::AxisAlignedBox getDimensions(MWWorld::CellStore*); //Ogre::AxisAlignedBox getDimensions(MWWorld::CellStore*);
///< get a bounding box that encloses all objects in the specified cell ///< get a bounding box that encloses all objects in the specified cell
bool deleteObject (const MWWorld::Ptr& ptr); bool deleteObject (const MWWorld::Ptr& ptr);
///< \return found? ///< \return found?
void removeCell(MWWorld::CellStore* store); void removeCell(const MWWorld::CellStore* store);
void setRootNode(Ogre::SceneNode* root);
void rebuildStaticGeometry();
/// Updates containing cell for object rendering data /// Updates containing cell for object rendering data
void updateObjectCell(const MWWorld::Ptr &old, const MWWorld::Ptr &cur); void updateObjectCell(const MWWorld::Ptr &old, const MWWorld::Ptr &cur);
private:
void operator = (const Objects&);
Objects(const Objects&);
}; };
} }
#endif #endif

File diff suppressed because it is too large Load Diff

@ -1,270 +1,61 @@
#ifndef GAME_RENDERING_MANAGER_H #ifndef OPENMW_MWRENDER_RENDERINGMANAGER_H
#define GAME_RENDERING_MANAGER_H #define OPENMW_MWRENDER_RENDERINGMANAGER_H
#include "sky.hpp" #include <osg/ref_ptr>
#include "debugging.hpp" #include <osg/Light>
#include <components/settings/settings.hpp> #include "objects.hpp"
#include <boost/filesystem.hpp>
#include <OgreRenderTargetListener.h>
#include "renderinginterface.hpp" #include "renderinginterface.hpp"
#include "objects.hpp" namespace osg
#include "actors.hpp"
#include "camera.hpp"
#include "occlusionquery.hpp"
namespace Ogre
{ {
class SceneNode; class Group;
} }
namespace MWWorld namespace Resource
{ {
class Ptr; class ResourceSystem;
class CellStore;
} }
namespace sh namespace osgViewer
{ {
class Factory; class Viewer;
} }
namespace Terrain namespace ESM
{ {
class World; struct Cell;
} }
namespace MWRender namespace MWRender
{ {
class Shadows;
class LocalMap;
class Water;
class GlobalMap;
class Animation;
class EffectManager;
class RenderingManager: private RenderingInterface, public Ogre::RenderTargetListener, public OEngine::Render::WindowSizeListener
{
private:
virtual MWRender::Objects& getObjects();
virtual MWRender::Actors& getActors();
public:
RenderingManager(OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir,
const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine,
MWWorld::Fallback* fallback);
virtual ~RenderingManager();
void togglePOV()
{ mCamera->toggleViewMode(); }
void togglePreviewMode(bool enable) class RenderingManager : public MWRender::RenderingInterface
{ mCamera->togglePreviewMode(enable); }
bool toggleVanityMode(bool enable)
{ return mCamera->toggleVanityMode(enable); }
void allowVanityMode(bool allow)
{ mCamera->allowVanityMode(allow); }
void togglePlayerLooking(bool enable)
{ mCamera->togglePlayerLooking(enable); }
void changeVanityModeScale(float factor)
{ {
if(mCamera->isVanityOrPreviewModeEnabled()) public:
mCamera->setCameraDistance(-factor/120.f*10, true, true); RenderingManager(osgViewer::Viewer& viewer, osg::ref_ptr<osg::Group> rootNode, Resource::ResourceSystem* resourceSystem);
}
void resetCamera();
bool vanityRotateCamera(const float *rot);
void setCameraDistance(float dist, bool adjust = false, bool override = true);
float getCameraDistance() const;
void setupPlayer(const MWWorld::Ptr &ptr);
void renderPlayer(const MWWorld::Ptr &ptr);
SkyManager* getSkyManager();
MWRender::Camera* getCamera() const;
bool toggleRenderMode(int mode);
void removeCell (MWWorld::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::CellStore *store);
/// Clear all savegame-specific data (i.e. fog of war textures)
void clear();
void enableTerrain(bool enable);
void removeWater();
/// Write current fog of war for this cell to the CellStore
void writeFog (MWWorld::CellStore* store);
void addObject (const MWWorld::Ptr& ptr, const std::string& model);
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);
/// Updates an object's rotation
void rotateObject (const MWWorld::Ptr& ptr);
void setWaterHeight(float height);
void setWaterEnabled(bool enabled);
bool toggleWater();
bool toggleWorld();
/// Updates object rendering after cell change
/// \param old Object reference in previous cell
/// \param cur Object reference in new cell
void updateObjectCell(const MWWorld::Ptr &old, const MWWorld::Ptr &cur);
/// Specifies an updated Ptr object for the player (used on cell change).
void updatePlayerPtr(const MWWorld::Ptr &ptr);
/// Currently for NPCs only. Rebuilds the NPC, updating their root model, animation sources,
/// and equipment.
void rebuildPtr(const MWWorld::Ptr &ptr);
void update (float duration, bool paused);
void setAmbientColour(const Ogre::ColourValue& colour);
void setSunColour(const Ogre::ColourValue& colour);
void setSunDirection(const Ogre::Vector3& direction, bool is_night);
void sunEnable(bool real); ///< @param real whether or not to really disable the sunlight (otherwise just set diffuse to 0)
void sunDisable(bool real);
void disableLights(bool sun); ///< @param sun whether or not to really disable the sunlight (otherwise just set diffuse to 0)
void enableLights(bool sun);
void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);
void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);
bool occlusionQuerySupported() { return mOcclusionQuery->supported(); }
OcclusionQuery* getOcclusionQuery() { return mOcclusionQuery; }
float getTerrainHeightAt (Ogre::Vector3 worldPos);
void notifyWorldSpaceChanged();
void getTriangleBatchCount(unsigned int &triangles, unsigned int &batches);
void setGlare(bool glare);
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(MWWorld::CellStore &mCell);
void addWaterRippleEmitter (const MWWorld::Ptr& ptr, float scale = 1.f, float force = 1.f);
void removeWaterRippleEmitter (const MWWorld::Ptr& ptr);
void updateWaterRippleEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr);
void updateTerrain ();
///< update the terrain according to the player position. Usually done automatically, but should be done manually
/// before calling requestMap
void requestMap (MWWorld::CellStore* cell);
///< request the local map for a cell
/// configure fog according to cell
void configureFog(const MWWorld::CellStore &mCell);
/// configure fog manually
void configureFog(const float density, const Ogre::ColourValue& colour);
Ogre::Vector4 boundingBoxToScreen(Ogre::AxisAlignedBox bounds);
///< transform the specified bounding box (in world coordinates) into screen coordinates.
/// @return packed vector4 (min_x, min_y, max_x, max_y)
void processChangedSettings(const Settings::CategorySettingVector& settings);
Ogre::Viewport* getViewport() { return mRendering.getViewport(); }
void worldToInteriorMapPosition (Ogre::Vector2 position, float& nX, float& nY, int &x, int& y);
///< see MWRender::LocalMap::worldToInteriorMapPosition
Ogre::Vector2 interiorMapToWorldPosition (float nX, float nY, int x, int y);
///< see MWRender::LocalMap::interiorMapToWorldPosition
bool isPositionExplored (float nX, float nY, int x, int y, bool interior);
///< see MWRender::LocalMap::isPositionExplored
Animation* getAnimation(const MWWorld::Ptr &ptr);
void frameStarted(float dt, bool paused);
void screenshot(Ogre::Image& image, int w, int h);
void spawnEffect (const std::string& model, const std::string& texture, const Ogre::Vector3& worldPosition, float scale=1.f);
protected:
virtual void windowResized(int x, int y);
private:
sh::Factory* mFactory;
void setAmbientMode();
void applyFog(bool underwater);
void attachCameraTo(const MWWorld::Ptr& ptr);
void setMenuTransparency(float val);
bool mSunEnabled;
MWWorld::Fallback* mFallback;
SkyManager* mSkyManager;
OcclusionQuery* mOcclusionQuery;
Terrain::World* mTerrain;
MWRender::Water *mWater;
GlobalMap* mGlobalMap;
OEngine::Render::OgreRenderer &mRendering;
MWRender::Objects* mObjects;
MWRender::Actors* mActors;
MWRender::EffectManager* mEffectManager;
MWRender::NpcAnimation *mPlayerAnimation; MWRender::Objects& getObjects();
MWRender::Actors& getActors();
Ogre::ColourValue mAmbientColor; Resource::ResourceSystem* getResourceSystem();
Ogre::Light* mSun;
Ogre::SceneNode *mRootNode; void configureAmbient(const ESM::Cell* cell);
Ogre::ColourValue mFogColour; void removeCell(const MWWorld::CellStore* store);
float mFogStart;
float mFogEnd;
OEngine::Physic::PhysicEngine* mPhysicsEngine; osg::Vec3f getEyePos();
MWRender::Camera *mCamera; private:
osgViewer::Viewer& mViewer;
osg::ref_ptr<osg::Group> mRootNode;
Resource::ResourceSystem* mResourceSystem;
MWRender::LocalMap* mLocalMap; osg::ref_ptr<osg::Light> mSunLight;
bool mRenderWorld; std::auto_ptr<Objects> mObjects;
}; };
} }

@ -686,10 +686,10 @@ namespace MWScript
else else
throw std::runtime_error ("invalid movement axis: " + axis); throw std::runtime_error ("invalid movement axis: " + axis);
if (!ptr.getRefData().getBaseNode()) if (!ptr.getRefData().getBaseNodeOld())
return; return;
Ogre::Vector3 diff = ptr.getRefData().getBaseNode()->getOrientation() * posChange; Ogre::Vector3 diff = ptr.getRefData().getBaseNodeOld()->getOrientation() * posChange;
Ogre::Vector3 worldPos(ptr.getRefData().getPosition().pos); Ogre::Vector3 worldPos(ptr.getRefData().getPosition().pos);
worldPos += diff; worldPos += diff;
MWBase::Environment::get().getWorld()->moveObject(ptr, worldPos.x, worldPos.y, worldPos.z); MWBase::Environment::get().getWorld()->moveObject(ptr, worldPos.x, worldPos.y, worldPos.z);

@ -20,11 +20,11 @@ namespace MWWorld
bool operator() (MWWorld::Ptr ptr) bool operator() (MWWorld::Ptr ptr)
{ {
Ogre::SceneNode* handle = ptr.getRefData().getBaseNode(); Ogre::SceneNode* handle = ptr.getRefData().getBaseNodeOld();
if (handle) if (handle)
mHandles.push_back (handle); mHandles.push_back (handle);
ptr.getRefData().setBaseNode(0); ptr.getRefData().setBaseNodeOld(0);
return true; return true;
} }
}; };

@ -242,7 +242,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr
MWWorld::Ptr item = *it; MWWorld::Ptr item = *it;
// we may have copied an item from the world, so reset a few things first // we may have copied an item from the world, so reset a few things first
item.getRefData().setBaseNode(NULL); // Especially important, otherwise scripts on the item could think that it's actually in a cell item.getRefData().setBaseNodeOld(NULL); // Especially important, otherwise scripts on the item could think that it's actually in a cell
ESM::Position pos; ESM::Position pos;
pos.rot[0] = 0; pos.rot[0] = 0;
pos.rot[1] = 0; pos.rot[1] = 0;

@ -653,7 +653,7 @@ namespace MWWorld
std::vector<std::string> PhysicsSystem::getCollisions(const Ptr &ptr, int collisionGroup, int collisionMask) std::vector<std::string> PhysicsSystem::getCollisions(const Ptr &ptr, int collisionGroup, int collisionMask)
{ {
return mEngine->getCollisions(ptr.getRefData().getBaseNode()->getName(), collisionGroup, collisionMask); return mEngine->getCollisions(ptr.getRefData().getBaseNodeOld()->getName(), collisionGroup, collisionMask);
} }
Ogre::Vector3 PhysicsSystem::traceDown(const MWWorld::Ptr &ptr, float maxHeight) Ogre::Vector3 PhysicsSystem::traceDown(const MWWorld::Ptr &ptr, float maxHeight)
@ -675,7 +675,7 @@ namespace MWWorld
void PhysicsSystem::addObject (const Ptr& ptr, const std::string& mesh, bool placeable) void PhysicsSystem::addObject (const Ptr& ptr, const std::string& mesh, bool placeable)
{ {
Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); Ogre::SceneNode* node = ptr.getRefData().getBaseNodeOld();
handleToMesh[node->getName()] = mesh; handleToMesh[node->getName()] = mesh;
mEngine->createAndAdjustRigidBody( mEngine->createAndAdjustRigidBody(
mesh, node->getName(), ptr.getCellRef().getScale(), node->getPosition(), node->getOrientation(), 0, 0, false, placeable); mesh, node->getName(), ptr.getCellRef().getScale(), node->getPosition(), node->getOrientation(), 0, 0, false, placeable);
@ -685,7 +685,7 @@ namespace MWWorld
void PhysicsSystem::addActor (const Ptr& ptr, const std::string& mesh) void PhysicsSystem::addActor (const Ptr& ptr, const std::string& mesh)
{ {
Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); Ogre::SceneNode* node = ptr.getRefData().getBaseNodeOld();
//TODO:optimize this. Searching the std::map isn't very efficient i think. //TODO:optimize this. Searching the std::map isn't very efficient i think.
mEngine->addCharacter(node->getName(), mesh, node->getPosition(), node->getScale().x, node->getOrientation()); mEngine->addCharacter(node->getName(), mesh, node->getPosition(), node->getScale().x, node->getOrientation());
} }
@ -699,7 +699,7 @@ namespace MWWorld
void PhysicsSystem::moveObject (const Ptr& ptr) void PhysicsSystem::moveObject (const Ptr& ptr)
{ {
Ogre::SceneNode *node = ptr.getRefData().getBaseNode(); Ogre::SceneNode *node = ptr.getRefData().getBaseNodeOld();
const std::string &handle = node->getName(); const std::string &handle = node->getName();
const Ogre::Vector3 &position = node->getPosition(); const Ogre::Vector3 &position = node->getPosition();
@ -722,7 +722,7 @@ namespace MWWorld
void PhysicsSystem::rotateObject (const Ptr& ptr) void PhysicsSystem::rotateObject (const Ptr& ptr)
{ {
Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); Ogre::SceneNode* node = ptr.getRefData().getBaseNodeOld();
const std::string &handle = node->getName(); const std::string &handle = node->getName();
const Ogre::Quaternion &rotation = node->getOrientation(); const Ogre::Quaternion &rotation = node->getOrientation();
@ -751,7 +751,7 @@ namespace MWWorld
void PhysicsSystem::scaleObject (const Ptr& ptr) void PhysicsSystem::scaleObject (const Ptr& ptr)
{ {
Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); Ogre::SceneNode* node = ptr.getRefData().getBaseNodeOld();
const std::string &handle = node->getName(); const std::string &handle = node->getName();
if(handleToMesh.find(handle) != handleToMesh.end()) if(handleToMesh.find(handle) != handleToMesh.end())
{ {

@ -134,14 +134,23 @@ namespace MWWorld
return mBaseNode->getName(); return mBaseNode->getName();
} }
Ogre::SceneNode* RefData::getBaseNode() Ogre::SceneNode* RefData::getBaseNodeOld()
{ {
return mBaseNode; return mBaseNode;
} }
void RefData::setBaseNode(Ogre::SceneNode* base) void RefData::setBaseNodeOld(Ogre::SceneNode* base)
{ {
mBaseNode = base; }
void RefData::setBaseNode(osg::PositionAttitudeTransform *base)
{
mBase = base;
}
osg::PositionAttitudeTransform* RefData::getBaseNode()
{
return mBase;
} }
int RefData::getCount() const int RefData::getCount() const

@ -10,6 +10,11 @@ namespace Ogre
class SceneNode; class SceneNode;
} }
namespace osg
{
class PositionAttitudeTransform;
}
namespace ESM namespace ESM
{ {
class Script; class Script;
@ -28,7 +33,7 @@ namespace MWWorld
class RefData class RefData
{ {
Ogre::SceneNode* mBaseNode; Ogre::SceneNode* mBaseNode;
osg::PositionAttitudeTransform* mBase;
MWScript::Locals mLocals; // if we find the overhead of heaving a locals MWScript::Locals mLocals; // if we find the overhead of heaving a locals
// object in the refdata of refs without a script, // object in the refdata of refs without a script,
@ -78,10 +83,18 @@ namespace MWWorld
const std::string &getHandle(); const std::string &getHandle();
/// Return OGRE base node (can be a null pointer). /// Return OGRE base node (can be a null pointer).
Ogre::SceneNode* getBaseNode(); /// obsolete
Ogre::SceneNode* getBaseNodeOld();
/// Return base node (can be a null pointer).
osg::PositionAttitudeTransform* getBaseNode();
/// Set OGRE base node (can be a null pointer). /// Set OGRE base node (can be a null pointer).
void setBaseNode (Ogre::SceneNode* base); /// obsolete
void setBaseNodeOld (Ogre::SceneNode* base);
/// Set base node (can be a null pointer).
void setBaseNode (osg::PositionAttitudeTransform* base);
int getCount() const; int getCount() const;

@ -6,12 +6,16 @@
#include <components/misc/resourcehelpers.hpp> #include <components/misc/resourcehelpers.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <osg/PositionAttitudeTransform>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwrender/renderingmanager.hpp"
//#include "physicssystem.hpp" //#include "physicssystem.hpp"
#include "player.hpp" #include "player.hpp"
#include "localscripts.hpp" #include "localscripts.hpp"
@ -20,19 +24,20 @@
#include "cellfunctors.hpp" #include "cellfunctors.hpp"
#include "cellstore.hpp" #include "cellstore.hpp"
#include <osg/Timer>
namespace namespace
{ {
#if 0 void addObject(const MWWorld::Ptr& ptr, //MWWorld::PhysicsSystem& physics,
void addObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics,
MWRender::RenderingManager& rendering) MWRender::RenderingManager& rendering)
{ {
std::string model = Misc::ResourceHelpers::correctActorModelPath(ptr.getClass().getModel(ptr)); std::string model = Misc::ResourceHelpers::correctActorModelPath(ptr.getClass().getModel(ptr), rendering.getResourceSystem()->getVFS());
std::string id = ptr.getClass().getId(ptr); std::string id = ptr.getClass().getId(ptr);
if (id == "prisonmarker" || id == "divinemarker" || id == "templemarker" || id == "northmarker") if (id == "prisonmarker" || id == "divinemarker" || id == "templemarker" || id == "northmarker")
model = ""; // marker objects that have a hardcoded function in the game logic, should be hidden from the player model = ""; // marker objects that have a hardcoded function in the game logic, should be hidden from the player
rendering.addObject(ptr, model); ptr.getClass().insertObjectRendering(ptr, model, rendering);
ptr.getClass().insertObject (ptr, model, physics); //ptr.getClass().insertObject (ptr, model, physics);
} }
void updateObjectLocalRotation (const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, void updateObjectLocalRotation (const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics,
@ -40,22 +45,21 @@ namespace
{ {
if (ptr.getRefData().getBaseNode() != NULL) if (ptr.getRefData().getBaseNode() != NULL)
{ {
Ogre::Quaternion worldRotQuat(Ogre::Radian(ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z); osg::Quat worldRotQuat(ptr.getRefData().getPosition().rot[2], osg::Vec3(0,0,-1));
if (!ptr.getClass().isActor()) if (!ptr.getClass().isActor())
worldRotQuat = Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X)* worldRotQuat = worldRotQuat * osg::Quat(ptr.getRefData().getPosition().rot[1], osg::Vec3(0,-1,0)) *
Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::NEGATIVE_UNIT_Y)* worldRotQuat; osg::Quat(ptr.getRefData().getPosition().rot[0], osg::Vec3(-1,0,0));
float x = ptr.getRefData().getLocalRotation().rot[0]; float x = ptr.getRefData().getLocalRotation().rot[0];
float y = ptr.getRefData().getLocalRotation().rot[1]; float y = ptr.getRefData().getLocalRotation().rot[1];
float z = ptr.getRefData().getLocalRotation().rot[2]; float z = ptr.getRefData().getLocalRotation().rot[2];
Ogre::Quaternion rot(Ogre::Radian(z), Ogre::Vector3::NEGATIVE_UNIT_Z); osg::Quat rot(z, osg::Vec3(0,0,-1));
if (!ptr.getClass().isActor()) if (!ptr.getClass().isActor())
rot = Ogre::Quaternion(Ogre::Radian(x), Ogre::Vector3::NEGATIVE_UNIT_X)* rot = rot * osg::Quat(y, osg::Vec3(0,-1,0)) * osg::Quat(x, osg::Vec3(-1,0,0));
Ogre::Quaternion(Ogre::Radian(y), Ogre::Vector3::NEGATIVE_UNIT_Y)*rot;
ptr.getRefData().getBaseNode()->setOrientation(worldRotQuat*rot); ptr.getRefData().getBaseNode()->setAttitude(rot * worldRotQuat);
physics.rotateObject(ptr); //physics.rotateObject(ptr);
} }
} }
@ -64,20 +68,21 @@ namespace
MWWorld::CellStore& mCell; MWWorld::CellStore& mCell;
bool mRescale; bool mRescale;
Loading::Listener& mLoadingListener; Loading::Listener& mLoadingListener;
MWWorld::PhysicsSystem& mPhysics; //MWWorld::PhysicsSystem& mPhysics;
MWRender::RenderingManager& mRendering; MWRender::RenderingManager& mRendering;
InsertFunctor (MWWorld::CellStore& cell, bool rescale, Loading::Listener& loadingListener, InsertFunctor (MWWorld::CellStore& cell, bool rescale, Loading::Listener& loadingListener,
MWWorld::PhysicsSystem& physics, MWRender::RenderingManager& rendering); /*MWWorld::PhysicsSystem& physics, */MWRender::RenderingManager& rendering);
bool operator() (const MWWorld::Ptr& ptr); bool operator() (const MWWorld::Ptr& ptr);
}; };
InsertFunctor::InsertFunctor (MWWorld::CellStore& cell, bool rescale, InsertFunctor::InsertFunctor (MWWorld::CellStore& cell, bool rescale,
Loading::Listener& loadingListener, MWWorld::PhysicsSystem& physics, Loading::Listener& loadingListener, /*MWWorld::PhysicsSystem& physics,*/
MWRender::RenderingManager& rendering) MWRender::RenderingManager& rendering)
: mCell (cell), mRescale (rescale), mLoadingListener (loadingListener), : mCell (cell), mRescale (rescale), mLoadingListener (loadingListener),
mPhysics (physics), mRendering (rendering) //mPhysics (physics),
mRendering (rendering)
{} {}
bool InsertFunctor::operator() (const MWWorld::Ptr& ptr) bool InsertFunctor::operator() (const MWWorld::Ptr& ptr)
@ -94,13 +99,13 @@ namespace
{ {
try try
{ {
addObject(ptr, mPhysics, mRendering); addObject(ptr, /*mPhysics, */mRendering);
updateObjectLocalRotation(ptr, mPhysics, mRendering); //updateObjectLocalRotation(ptr, mPhysics, mRendering);
if (ptr.getRefData().getBaseNode()) if (ptr.getRefData().getBaseNode())
{ {
float scale = ptr.getCellRef().getScale(); float scale = ptr.getCellRef().getScale();
ptr.getClass().adjustScale(ptr, scale); ptr.getClass().adjustScale(ptr, scale);
mRendering.scaleObject(ptr, Ogre::Vector3(scale)); //mRendering.scaleObject(ptr, Ogre::Vector3(scale));
} }
ptr.getClass().adjustPosition (ptr, false); ptr.getClass().adjustPosition (ptr, false);
} }
@ -115,7 +120,6 @@ namespace
return true; return true;
} }
#endif
} }
@ -129,7 +133,7 @@ namespace MWWorld
void Scene::updateObjectRotation (const Ptr& ptr) void Scene::updateObjectRotation (const Ptr& ptr)
{ {
if(ptr.getRefData().getBaseNode() != 0) if(ptr.getRefData().getBaseNodeOld() != 0)
{ {
//mRendering.rotateObject(ptr); //mRendering.rotateObject(ptr);
//mPhysics->rotateObject(ptr); //mPhysics->rotateObject(ptr);
@ -190,23 +194,24 @@ namespace MWWorld
for (std::vector<Ogre::SceneNode*>::const_iterator iter2 (functor.mHandles.begin()); for (std::vector<Ogre::SceneNode*>::const_iterator iter2 (functor.mHandles.begin());
iter2!=functor.mHandles.end(); ++iter2) iter2!=functor.mHandles.end(); ++iter2)
{ {
Ogre::SceneNode* node = *iter2; //Ogre::SceneNode* node = *iter2;
//mPhysics->removeObject (node->getName()); //mPhysics->removeObject (node->getName());
} }
} }
if ((*iter)->getCell()->isExterior()) if ((*iter)->getCell()->isExterior())
{ {
ESM::Land* land = /*ESM::Land* land =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Land>().search( MWBase::Environment::get().getWorld()->getStore().get<ESM::Land>().search(
(*iter)->getCell()->getGridX(), (*iter)->getCell()->getGridX(),
(*iter)->getCell()->getGridY() (*iter)->getCell()->getGridY()
); );
//if (land && land->mDataTypes&ESM::Land::DATA_VHGT) if (land && land->mDataTypes&ESM::Land::DATA_VHGT)
//mPhysics->removeHeightField ((*iter)->getCell()->getGridX(), (*iter)->getCell()->getGridY()); mPhysics->removeHeightField ((*iter)->getCell()->getGridX(), (*iter)->getCell()->getGridY());
*/
} }
//mRendering.removeCell(*iter); mRendering.removeCell(*iter);
MWBase::Environment::get().getWorld()->getLocalScripts().clearCell (*iter); MWBase::Environment::get().getWorld()->getLocalScripts().clearCell (*iter);
@ -224,8 +229,8 @@ namespace MWWorld
{ {
std::cout << "loading cell " << cell->getCell()->getDescription() << std::endl; std::cout << "loading cell " << cell->getCell()->getDescription() << std::endl;
float verts = ESM::Land::LAND_SIZE; //float verts = ESM::Land::LAND_SIZE;
float worldsize = ESM::Land::REAL_SIZE; //float worldsize = ESM::Land::REAL_SIZE;
#if 0 #if 0
// Load terrain physics first... // Load terrain physics first...
@ -271,9 +276,9 @@ namespace MWWorld
} }
else else
mPhysics->disableWater(); mPhysics->disableWater();
mRendering.configureAmbient(*cell);
#endif #endif
if (!cell->isExterior() && !(cell->getCell()->mData.mFlags & ESM::Cell::QuasiEx))
mRendering.configureAmbient(cell->getCell());
} }
// register local scripts // register local scripts
@ -290,7 +295,7 @@ namespace MWWorld
mCurrentCell = NULL; mCurrentCell = NULL;
} }
void Scene::playerMoved(const Ogre::Vector3 &pos) void Scene::playerMoved(const osg::Vec3f &pos)
{ {
if (!mCurrentCell || !mCurrentCell->isExterior()) if (!mCurrentCell || !mCurrentCell->isExterior())
return; return;
@ -301,12 +306,14 @@ namespace MWWorld
float centerX, centerY; float centerX, centerY;
MWBase::Environment::get().getWorld()->indexToPosition(cellX, cellY, centerX, centerY, true); MWBase::Environment::get().getWorld()->indexToPosition(cellX, cellY, centerX, centerY, true);
const float maxDistance = 8192/2 + 1024; // 1/2 cell size + threshold const float maxDistance = 8192/2 + 1024; // 1/2 cell size + threshold
float distance = std::max(std::abs(centerX-pos.x), std::abs(centerY-pos.y)); float distance = std::max(std::abs(centerX-pos.x()), std::abs(centerY-pos.y()));
if (distance > maxDistance) if (distance > maxDistance)
{ {
int newX, newY; int newX, newY;
MWBase::Environment::get().getWorld()->positionToIndex(pos.x, pos.y, newX, newY); MWBase::Environment::get().getWorld()->positionToIndex(pos.x(), pos.y(), newX, newY);
osg::Timer timer;
changeCellGrid(newX, newY); changeCellGrid(newX, newY);
std::cout << "changeCellGrid took " << timer.time_m() << std::endl;
//mRendering.updateTerrain(); //mRendering.updateTerrain();
} }
} }
@ -435,7 +442,7 @@ namespace MWWorld
//We need the ogre renderer and a scene node. //We need the ogre renderer and a scene node.
Scene::Scene (MWRender::RenderingManager& rendering, PhysicsSystem *physics) Scene::Scene (MWRender::RenderingManager& rendering, PhysicsSystem *physics)
: mCurrentCell (0), mCellChanged (false), /*mPhysics(physics), mRendering(rendering),*/ mNeedMapUpdate(false) : mCurrentCell (0), mCellChanged (false), /*mPhysics(physics),*/ mRendering(rendering), mNeedMapUpdate(false)
{ {
} }
@ -545,15 +552,15 @@ namespace MWWorld
void Scene::insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener) void Scene::insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener)
{ {
//InsertFunctor functor (cell, rescale, *loadingListener, *mPhysics, mRendering); InsertFunctor functor (cell, rescale, *loadingListener, /* *mPhysics, */mRendering);
//cell.forEach (functor); cell.forEach (functor);
} }
void Scene::addObjectToScene (const Ptr& ptr) void Scene::addObjectToScene (const Ptr& ptr)
{ {
try try
{ {
//addObject(ptr, *mPhysics, mRendering); addObject(ptr, /* *mPhysics, */mRendering);
//MWBase::Environment::get().getWorld()->rotateObject(ptr, 0, 0, 0, true); //MWBase::Environment::get().getWorld()->rotateObject(ptr, 0, 0, 0, true);
//MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().getScale()); //MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().getScale());
} }

@ -8,6 +8,11 @@
#include <set> #include <set>
namespace osg
{
class Vec3f;
}
namespace Ogre namespace Ogre
{ {
class Vector3; class Vector3;
@ -59,7 +64,7 @@ namespace MWWorld
CellStoreCollection mActiveCells; CellStoreCollection mActiveCells;
bool mCellChanged; bool mCellChanged;
//PhysicsSystem *mPhysics; //PhysicsSystem *mPhysics;
//MWRender::RenderingManager& mRendering; MWRender::RenderingManager& mRendering;
bool mNeedMapUpdate; bool mNeedMapUpdate;
@ -80,7 +85,7 @@ namespace MWWorld
void loadCell (CellStore *cell, Loading::Listener* loadingListener); void loadCell (CellStore *cell, Loading::Listener* loadingListener);
void playerMoved (const Ogre::Vector3& pos); void playerMoved (const osg::Vec3f& pos);
void changePlayerCell (CellStore* newCell, const ESM::Position& position, bool adjustPlayerPos); void changePlayerCell (CellStore* newCell, const ESM::Position& position, bool adjustPlayerPos);

@ -11,6 +11,8 @@
#include "../mwscript/globalscripts.hpp" #include "../mwscript/globalscripts.hpp"
#include <OgreSceneNode.h> #include <OgreSceneNode.h>
#include <osg/Group>
#include <libs/openengine/bullet/trace.h> #include <libs/openengine/bullet/trace.h>
#include <libs/openengine/bullet/physic.hpp> #include <libs/openengine/bullet/physic.hpp>
@ -37,6 +39,7 @@
#include "../mwmechanics/aiavoiddoor.hpp" //Used to tell actors to avoid doors #include "../mwmechanics/aiavoiddoor.hpp" //Used to tell actors to avoid doors
//#include "../mwrender/animation.hpp" //#include "../mwrender/animation.hpp"
#include "../mwrender/renderingmanager.hpp"
#include "../mwscript/interpretercontext.hpp" #include "../mwscript/interpretercontext.hpp"
@ -143,9 +146,11 @@ namespace MWWorld
} }
World::World ( World::World (
osgViewer::Viewer& viewer,
osg::ref_ptr<osg::Group> rootNode,
Resource::ResourceSystem* resourceSystem,
const Files::Collections& fileCollections, const Files::Collections& fileCollections,
const std::vector<std::string>& contentFiles, const std::vector<std::string>& contentFiles,
const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir,
ToUTF8::Utf8Encoder* encoder, const std::map<std::string,std::string>& fallbackMap, ToUTF8::Utf8Encoder* encoder, const std::map<std::string,std::string>& fallbackMap,
int activationDistanceOverride, const std::string& startCell, const std::string& startupScript) int activationDistanceOverride, const std::string& startCell, const std::string& startupScript)
: mPlayer (0), mLocalScripts (mStore), : mPlayer (0), mLocalScripts (mStore),
@ -162,7 +167,7 @@ namespace MWWorld
#if 0 #if 0
mProjectileManager.reset(new ProjectileManager(renderer.getScene(), *mPhysEngine)); mProjectileManager.reset(new ProjectileManager(renderer.getScene(), *mPhysEngine));
#endif #endif
//mRendering = new MWRender::RenderingManager(renderer, resDir, cacheDir, mPhysEngine,&mFallback); mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem);
//mPhysEngine->setSceneManager(renderer.getScene()); //mPhysEngine->setSceneManager(renderer.getScene());
@ -476,7 +481,7 @@ namespace MWWorld
#endif #endif
//delete mWeatherManager; //delete mWeatherManager;
delete mWorldScene; delete mWorldScene;
//delete mRendering; delete mRendering;
//delete mPhysics; //delete mPhysics;
delete mPlayer; delete mPlayer;
@ -1184,7 +1189,7 @@ namespace MWWorld
MWWorld::Ptr newPtr = ptr.getClass() MWWorld::Ptr newPtr = ptr.getClass()
.copyToCell(ptr, *newCell); .copyToCell(ptr, *newCell);
newPtr.getRefData().setBaseNode(0); newPtr.getRefData().setBaseNodeOld(0);
} }
else if (!currCellActive && !newCellActive) else if (!currCellActive && !newCellActive)
ptr.getClass().copyToCell(ptr, *newCell); ptr.getClass().copyToCell(ptr, *newCell);
@ -1194,7 +1199,7 @@ namespace MWWorld
ptr.getClass().copyToCell(ptr, *newCell, pos); ptr.getClass().copyToCell(ptr, *newCell, pos);
//mRendering->updateObjectCell(ptr, copy); //mRendering->updateObjectCell(ptr, copy);
ptr.getRefData().setBaseNode(NULL); ptr.getRefData().setBaseNodeOld(NULL);
MWBase::Environment::get().getSoundManager()->updatePtr (ptr, copy); MWBase::Environment::get().getSoundManager()->updatePtr (ptr, copy);
MWBase::MechanicsManager *mechMgr = MWBase::Environment::get().getMechanicsManager(); MWBase::MechanicsManager *mechMgr = MWBase::Environment::get().getMechanicsManager();
@ -1213,14 +1218,14 @@ namespace MWWorld
ptr.getRefData().setCount(0); ptr.getRefData().setCount(0);
} }
} }
if (haveToMove && ptr.getRefData().getBaseNode()) if (haveToMove && ptr.getRefData().getBaseNodeOld())
{ {
//mRendering->moveObject(ptr, vec); //mRendering->moveObject(ptr, vec);
//mPhysics->moveObject (ptr); //mPhysics->moveObject (ptr);
} }
if (isPlayer) if (isPlayer)
{ {
mWorldScene->playerMoved (vec); //mWorldScene->playerMoved (vec);
} }
} }
@ -1252,7 +1257,7 @@ namespace MWWorld
ptr.getCellRef().setScale(scale); ptr.getCellRef().setScale(scale);
ptr.getClass().adjustScale(ptr,scale); ptr.getClass().adjustScale(ptr,scale);
if(ptr.getRefData().getBaseNode() == 0) if(ptr.getRefData().getBaseNodeOld() == 0)
return; return;
//mRendering->scaleObject(ptr, Vector3(scale,scale,scale)); //mRendering->scaleObject(ptr, Vector3(scale,scale,scale));
//mPhysics->scaleObject(ptr); //mPhysics->scaleObject(ptr);
@ -1303,7 +1308,7 @@ namespace MWWorld
ptr.getRefData().setPosition(pos); ptr.getRefData().setPosition(pos);
if(ptr.getRefData().getBaseNode() == 0) if(ptr.getRefData().getBaseNodeOld() == 0)
return; return;
if (ptr.getClass().isActor()) if (ptr.getClass().isActor())
@ -1325,7 +1330,7 @@ namespace MWWorld
ptr.getRefData().setLocalRotation(rot); ptr.getRefData().setLocalRotation(rot);
if (ptr.getRefData().getBaseNode() != 0) if (ptr.getRefData().getBaseNodeOld() != 0)
{ {
mWorldScene->updateObjectLocalRotation(ptr); mWorldScene->updateObjectLocalRotation(ptr);
} }
@ -1335,7 +1340,7 @@ namespace MWWorld
{ {
ESM::Position pos (ptr.getRefData().getPosition()); ESM::Position pos (ptr.getRefData().getPosition());
if(!ptr.getRefData().getBaseNode()) if(!ptr.getRefData().getBaseNodeOld())
{ {
// will be adjusted when Ptr's cell becomes active // will be adjusted when Ptr's cell becomes active
return; return;
@ -1352,9 +1357,9 @@ namespace MWWorld
if (force || !isFlying(ptr)) if (force || !isFlying(ptr))
{ {
Ogre::Vector3 traced;// = mPhysics->traceDown(ptr, 500); //Ogre::Vector3 traced = mPhysics->traceDown(ptr, 500);
if (traced.z < pos.pos[2]) //if (traced.z < pos.pos[2])
pos.pos[2] = traced.z; // pos.pos[2] = traced.z;
} }
moveObject(ptr, ptr.getCell(), pos.pos[0], pos.pos[1], pos.pos[2]); moveObject(ptr, ptr.getCell(), pos.pos[0], pos.pos[1], pos.pos[2]);
@ -1599,13 +1604,14 @@ namespace MWWorld
void World::update (float duration, bool paused) void World::update (float duration, bool paused)
{ {
/*
if (mGoToJail && !paused) if (mGoToJail && !paused)
goToJail(); goToJail();
updateWeather(duration, paused); updateWeather(duration, paused);
//if (!paused) if (!paused)
// doPhysics (duration); doPhysics (duration);
mWorldScene->update (duration, paused); mWorldScene->update (duration, paused);
@ -1620,11 +1626,14 @@ namespace MWWorld
ESM::Position pos = mPlayer->getPlayer().getRefData().getPosition(); ESM::Position pos = mPlayer->getPlayer().getRefData().getPosition();
mPlayer->setLastKnownExteriorPosition(Ogre::Vector3(pos.pos)); mPlayer->setLastKnownExteriorPosition(Ogre::Vector3(pos.pos));
} }
*/
//mWorldScene->playerMoved(mRendering->getEyePos());
} }
void World::updateSoundListener() void World::updateSoundListener()
{ {
Ogre::Vector3 playerPos = mPlayer->getPlayer().getRefData().getBaseNode()->getPosition(); Ogre::Vector3 playerPos = mPlayer->getPlayer().getRefData().getBaseNodeOld()->getPosition();
const OEngine::Physic::PhysicActor *actor = mPhysEngine->getCharacter(getPlayerPtr().getRefData().getHandle()); const OEngine::Physic::PhysicActor *actor = mPhysEngine->getCharacter(getPlayerPtr().getRefData().getHandle());
if(actor) playerPos.z += 1.85f * actor->getHalfExtents().z; if(actor) playerPos.z += 1.85f * actor->getHalfExtents().z;
Ogre::Quaternion playerOrient = Ogre::Quaternion(Ogre::Radian(getPlayerPtr().getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) * Ogre::Quaternion playerOrient = Ogre::Quaternion(Ogre::Radian(getPlayerPtr().getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) *
@ -1644,7 +1653,7 @@ namespace MWWorld
// retrieve object dimensions so we know where to place the floating label // retrieve object dimensions so we know where to place the floating label
if (!object.isEmpty ()) if (!object.isEmpty ())
{ {
Ogre::SceneNode* node = object.getRefData().getBaseNode(); Ogre::SceneNode* node = object.getRefData().getBaseNodeOld();
Ogre::AxisAlignedBox bounds = node->_getWorldAABB(); Ogre::AxisAlignedBox bounds = node->_getWorldAABB();
if (bounds.isFinite()) if (bounds.isFinite())
{ {
@ -2341,7 +2350,7 @@ namespace MWWorld
bool operator() (Ptr ptr) bool operator() (Ptr ptr)
{ {
Ogre::SceneNode* handle = ptr.getRefData().getBaseNode(); Ogre::SceneNode* handle = ptr.getRefData().getBaseNodeOld();
if (handle) if (handle)
mHandles.push_back(handle->getName()); mHandles.push_back(handle->getName());
return true; return true;
@ -2366,7 +2375,7 @@ namespace MWWorld
{ {
if (!targetActor.getRefData().isEnabled() || !actor.getRefData().isEnabled()) if (!targetActor.getRefData().isEnabled() || !actor.getRefData().isEnabled())
return false; // cannot get LOS unless both NPC's are enabled return false; // cannot get LOS unless both NPC's are enabled
if (!targetActor.getRefData().getBaseNode() || !targetActor.getRefData().getBaseNode()) if (!targetActor.getRefData().getBaseNodeOld() || !targetActor.getRefData().getBaseNodeOld())
return false; // not in active cell return false; // not in active cell
OEngine::Physic::PhysicActor* actor1 = mPhysEngine->getCharacter(actor.getRefData().getHandle()); OEngine::Physic::PhysicActor* actor1 = mPhysEngine->getCharacter(actor.getRefData().getHandle());

@ -5,6 +5,8 @@
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <osg/ref_ptr>
#include "ptr.hpp" #include "ptr.hpp"
#include "scene.hpp" #include "scene.hpp"
#include "esmstore.hpp" #include "esmstore.hpp"
@ -21,6 +23,21 @@
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
namespace osg
{
class Group;
}
namespace osgViewer
{
class Viewer;
}
namespace Resource
{
class ResourceSystem;
}
namespace Ogre namespace Ogre
{ {
class Vector3; class Vector3;
@ -155,9 +172,11 @@ namespace MWWorld
public: public:
World ( World (
osgViewer::Viewer& viewer,
osg::ref_ptr<osg::Group> rootNode,
Resource::ResourceSystem* resourceSystem,
const Files::Collections& fileCollections, const Files::Collections& fileCollections,
const std::vector<std::string>& contentFiles, const std::vector<std::string>& contentFiles,
const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir,
ToUTF8::Utf8Encoder* encoder, const std::map<std::string,std::string>& fallbackMap, ToUTF8::Utf8Encoder* encoder, const std::map<std::string,std::string>& fallbackMap,
int activationDistanceOverride, const std::string& startCell, const std::string& startupScript); int activationDistanceOverride, const std::string& startCell, const std::string& startupScript);

@ -74,6 +74,16 @@ namespace SceneUtil
if (lights.size()) if (lights.size())
{ {
static std::map<osg::Node*, osg::ref_ptr<osg::StateSet> > statesets;
std::map<osg::Node*, osg::ref_ptr<osg::StateSet> >::iterator found = statesets.find(node);
osg::ref_ptr<osg::StateSet> stateset;
if (found != statesets.end())
{
stateset = found->second;
}
else{
// we do the intersections in view space // we do the intersections in view space
osg::BoundingSphere nodeBound = node->getBound(); osg::BoundingSphere nodeBound = node->getBound();
osg::Matrixf mat = *cv->getModelViewMatrix(); osg::Matrixf mat = *cv->getModelViewMatrix();
@ -89,26 +99,33 @@ namespace SceneUtil
if (lightList.empty()) if (lightList.empty())
{ {
statesets[node] = NULL;
traverse(node, nv); traverse(node, nv);
return; return;
} }
if (lightList.size() > 8) unsigned int maxLights = static_cast<unsigned int> (8 - mLightManager->getStartLight());
if (lightList.size() > maxLights)
{ {
//std::cerr << "More than 8 lights!" << std::endl; //std::cerr << "More than 8 lights!" << std::endl;
// TODO: sort lights by certain criteria // TODO: sort lights by certain criteria
while (lightList.size() > 8) while (lightList.size() > maxLights)
lightList.pop_back(); lightList.pop_back();
} }
osg::ref_ptr<osg::StateSet> stateset = mLightManager->getLightListStateSet(lightList); stateset = mLightManager->getLightListStateSet(lightList);
statesets[node] = stateset;
}
if (stateset)
cv->pushStateSet(stateset); cv->pushStateSet(stateset);
traverse(node, nv); traverse(node, nv);
if (stateset)
cv->popStateSet(); cv->popStateSet();
} }
else else
@ -174,7 +191,7 @@ namespace SceneUtil
throw std::runtime_error("can't find parent LightManager"); throw std::runtime_error("can't find parent LightManager");
} }
mLightManager->addLight(static_cast<LightSource*>(node), osg::computeLocalToWorld(nv->getNodePath())); //mLightManager->addLight(static_cast<LightSource*>(node), osg::computeLocalToWorld(nv->getNodePath()));
traverse(node, nv); traverse(node, nv);
} }
@ -208,6 +225,7 @@ namespace SceneUtil
LightManager::LightManager() LightManager::LightManager()
: mLightsInViewSpace(false) : mLightsInViewSpace(false)
, mDecorated(false) , mDecorated(false)
, mStartLight(0)
{ {
setUpdateCallback(new LightManagerUpdateCallback); setUpdateCallback(new LightManagerUpdateCallback);
} }
@ -216,6 +234,7 @@ namespace SceneUtil
: osg::Group(copy, copyop) : osg::Group(copy, copyop)
, mLightsInViewSpace(false) , mLightsInViewSpace(false)
, mDecorated(copy.mDecorated) , mDecorated(copy.mDecorated)
, mStartLight(copy.mStartLight)
{ {
} }
@ -284,11 +303,14 @@ namespace SceneUtil
osg::ref_ptr<LightStateAttribute> clonedLight = new LightStateAttribute(*light, osg::CopyOp::DEEP_COPY_ALL); osg::ref_ptr<LightStateAttribute> clonedLight = new LightStateAttribute(*light, osg::CopyOp::DEEP_COPY_ALL);
clonedLight->setPosition(mLights[lightIndex].mWorldMatrix.preMult(light->getPosition())); clonedLight->setPosition(mLights[lightIndex].mWorldMatrix.preMult(light->getPosition()));
clonedLight->setLightNum(i); clonedLight->setLightNum(i+mStartLight);
// don't use setAttributeAndModes, that does not support light indices! // don't use setAttributeAndModes, that does not support light indices!
stateset->setAttribute(clonedLight, osg::StateAttribute::ON); stateset->setAttribute(clonedLight, osg::StateAttribute::ON);
stateset->setAssociatedModes(clonedLight, osg::StateAttribute::ON); stateset->setAssociatedModes(clonedLight, osg::StateAttribute::ON);
//stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
} }
mStateSetCache.insert(std::make_pair(hash, stateset)); mStateSetCache.insert(std::make_pair(hash, stateset));
return stateset; return stateset;
@ -300,6 +322,16 @@ namespace SceneUtil
return mLights; return mLights;
} }
void LightManager::setStartLight(int start)
{
mStartLight = start;
}
int LightManager::getStartLight() const
{
return mStartLight;
}
LightSource::LightSource() LightSource::LightSource()
: mRadius(0.f) : mRadius(0.f)
{ {

@ -87,6 +87,11 @@ namespace SceneUtil
osg::ref_ptr<osg::StateSet> getLightListStateSet(const LightList& lightList); osg::ref_ptr<osg::StateSet> getLightListStateSet(const LightList& lightList);
/// Set the first light index that should be used by this manager, typically the number of directional lights in the scene.
void setStartLight(int start);
int getStartLight() const;
private: private:
// Lights collected from the scene graph. Only valid during the cull traversal. // Lights collected from the scene graph. Only valid during the cull traversal.
std::vector<LightSourceTransform> mLights; std::vector<LightSourceTransform> mLights;
@ -98,6 +103,8 @@ namespace SceneUtil
LightStateSetMap mStateSetCache; LightStateSetMap mStateSetCache;
bool mDecorated; bool mDecorated;
int mStartLight;
}; };
} }

@ -129,15 +129,6 @@ local map hud widget size = 256
exterior grid size = 3 exterior grid size = 3
[Viewing distance] [Viewing distance]
# Limit the rendering distance of small objects
limit small object distance = false
# Size below which an object is considered as small
small object size = 250
# Rendering distance for small objects
small object distance = 3500
# Viewing distance at normal weather conditions # Viewing distance at normal weather conditions
# The maximum distance with no pop-in will be: (see RenderingManager::configureFog) # The maximum distance with no pop-in will be: (see RenderingManager::configureFog)
# viewing distance / minimum weather fog depth (.69) * view frustum factor <= cell size (8192) - loading threshold (1024) # viewing distance / minimum weather fog depth (.69) * view frustum factor <= cell size (8192) - loading threshold (1024)

Loading…
Cancel
Save