Use Animation-derived objects for generic objects

actorid
Chris Robinson 12 years ago
parent a9dca21d05
commit 3555476dfd

@ -34,11 +34,10 @@ namespace MWClass
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
if(!model.empty())
objects.insertMesh(ptr, "meshes\\" + model, true);
objects.insertMesh(ptr, "meshes\\" + model);
else
objects.insertLight(ptr);
objects.insertMesh(ptr, "");
}
void Light::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const

@ -9,6 +9,7 @@
#include <OgreSubMesh.h>
#include <OgreSceneManager.h>
#include <OgreControllerManager.h>
#include <OgreStaticGeometry.h>
#include <libs/openengine/ogre/lights.hpp>
@ -21,6 +22,8 @@
#include "../mwworld/class.hpp"
#include "../mwworld/fallback.hpp"
#include "renderconst.hpp"
namespace MWRender
{
@ -91,6 +94,12 @@ void Animation::setObjectRoot(const std::string &model, bool baseonly)
{
OgreAssert(mAnimSources.empty(), "Setting object root while animation sources are set!");
mSkelBase = NULL;
destroyObjectList(mInsert->getCreator(), mObjectRoot);
if(model.empty())
return;
std::string mdlname = Misc::StringUtils::lowerCase(model);
std::string::size_type p = mdlname.rfind('\\');
if(p == std::string::npos)
@ -105,9 +114,6 @@ void Animation::setObjectRoot(const std::string &model, bool baseonly)
Misc::StringUtils::toLower(mdlname);
}
mSkelBase = NULL;
destroyObjectList(mInsert->getCreator(), mObjectRoot);
mObjectRoot = (!baseonly ? NifOgre::Loader::createObjects(mInsert, mdlname) :
NifOgre::Loader::createObjectBase(mInsert, mdlname));
if(mObjectRoot.mSkelBase)
@ -157,16 +163,18 @@ void Animation::setObjectRoot(const std::string &model, bool baseonly)
class VisQueueSet {
Ogre::uint32 mVisFlags;
Ogre::uint8 mSolidQueue, mTransQueue;
Ogre::Real mDist;
public:
VisQueueSet(Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue)
: mVisFlags(visflags), mSolidQueue(solidqueue), mTransQueue(transqueue)
VisQueueSet(Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue, Ogre::Real dist)
: mVisFlags(visflags), mSolidQueue(solidqueue), mTransQueue(transqueue), mDist(dist)
{ }
void operator()(Ogre::Entity *entity) const
{
if(mVisFlags != 0)
entity->setVisibilityFlags(mVisFlags);
entity->setRenderingDistance(mDist);
unsigned int numsubs = entity->getNumSubEntities();
for(unsigned int i = 0;i < numsubs;++i)
@ -180,17 +188,18 @@ public:
{
if(mVisFlags != 0)
psys->setVisibilityFlags(mVisFlags);
psys->setRenderingDistance(mDist);
// TODO: Check particle material for actual transparency
psys->setRenderQueueGroup(mTransQueue);
}
};
void Animation::setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue)
void Animation::setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue, Ogre::Real dist)
{
std::for_each(objlist.mEntities.begin(), objlist.mEntities.end(),
VisQueueSet(visflags, solidqueue, transqueue));
VisQueueSet(visflags, solidqueue, transqueue, dist));
std::for_each(objlist.mParticles.begin(), objlist.mParticles.end(),
VisQueueSet(visflags, solidqueue, transqueue));
VisQueueSet(visflags, solidqueue, transqueue, dist));
}
@ -903,6 +912,43 @@ void Animation::showWeapons(bool showWeapon)
{
}
class ToggleLight {
bool mEnable;
public:
ToggleLight(bool enable) : mEnable(enable) { }
void operator()(Ogre::Light *light) const
{ light->setVisible(mEnable); }
};
void Animation::enableLights(bool enable)
{
std::for_each(mObjectRoot.mLights.begin(), mObjectRoot.mLights.end(), ToggleLight(enable));
}
class MergeBounds {
Ogre::AxisAlignedBox *mBounds;
public:
MergeBounds(Ogre::AxisAlignedBox *bounds) : mBounds(bounds) { }
void operator()(Ogre::MovableObject *obj)
{
mBounds->merge(obj->getWorldBoundingBox(true));
}
};
Ogre::AxisAlignedBox Animation::getWorldBounds()
{
Ogre::AxisAlignedBox bounds = Ogre::AxisAlignedBox::BOX_NULL;
std::for_each(mObjectRoot.mEntities.begin(), mObjectRoot.mEntities.end(), MergeBounds(&bounds));
return bounds;
}
bool Animation::isPriorityActive(int priority) const
{
for (AnimStateMap::const_iterator it = mStates.begin(); it != mStates.end(); ++it)
@ -931,4 +977,65 @@ void Animation::detachObjectFromBone(Ogre::MovableObject *obj)
mSkelBase->detachObjectFromBone(obj);
}
ObjectAnimation::ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model, bool isStatic)
: Animation(ptr, ptr.getRefData().getBaseNode())
{
setObjectRoot(model, false);
Ogre::AxisAlignedBox bounds = getWorldBounds();
Ogre::Vector3 extents = bounds.getSize();
extents *= mInsert->getParentSceneNode()->getScale();
float size = std::max(std::max(extents.x, extents.y), extents.z);
bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) &&
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;
float dist = small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0.0f;
setRenderProperties(mObjectRoot, isStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc,
RQG_Main, RQG_Alpha, dist);
}
void ObjectAnimation::addLight(const ESM::Light *light)
{
addExtraLight(mInsert->getCreator(), mObjectRoot, light);
}
class FindEntityTransparency {
public:
bool operator()(Ogre::Entity *ent) const
{
unsigned int numsubs = ent->getNumSubEntities();
for(unsigned int i = 0;i < numsubs;++i)
{
if(ent->getSubEntity(i)->getMaterial()->isTransparent())
return true;
}
return false;
}
};
bool ObjectAnimation::canBatch() const
{
if(!mObjectRoot.mParticles.empty() || !mObjectRoot.mLights.empty() || !mObjectRoot.mControllers.empty())
return false;
return std::find_if(mObjectRoot.mEntities.begin(), mObjectRoot.mEntities.end(),
FindEntityTransparency()) == mObjectRoot.mEntities.end();
}
void ObjectAnimation::fillBatch(Ogre::StaticGeometry *sg)
{
std::vector<Ogre::Entity*>::reverse_iterator iter = mObjectRoot.mEntities.rbegin();
for(;iter != mObjectRoot.mEntities.rend();++iter)
{
Ogre::Node *node = (*iter)->getParentNode();
sg->addEntity(*iter, node->_getDerivedPosition(), node->_getDerivedOrientation(), node->_getDerivedScale());
}
}
}

@ -165,7 +165,7 @@ protected:
static void destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects);
static void setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue);
static void setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue, Ogre::Real dist=0.0f);
void clearAnimSources();
@ -229,6 +229,10 @@ public:
virtual void showWeapons(bool showWeapon);
void enableLights(bool enable);
Ogre::AxisAlignedBox getWorldBounds();
void setCamera(Camera *cam)
{ mCamera = cam; }
@ -241,5 +245,15 @@ public:
void detachObjectFromBone(Ogre::MovableObject *obj);
};
class ObjectAnimation : public Animation {
public:
ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model, bool isStatic);
void addLight(const ESM::Light *light);
bool canBatch() const;
void fillBatch(Ogre::StaticGeometry *sg);
};
}
#endif

@ -18,6 +18,7 @@
#include "../mwworld/class.hpp"
#include "renderconst.hpp"
#include "animation.hpp"
using namespace MWRender;
float Objects::lightLinearValue()
@ -124,22 +125,20 @@ void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_)
mIsStatic = static_;
}
void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool light)
void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
{
Ogre::SceneNode* insert = ptr.getRefData().getBaseNode();
assert(insert);
Ogre::AxisAlignedBox bounds = Ogre::AxisAlignedBox::BOX_NULL;
NifOgre::ObjectList objects = NifOgre::Loader::createObjects(insert, mesh);
for(size_t i = 0;i < objects.mEntities.size();i++)
bounds.merge(objects.mEntities[i]->getWorldBoundingBox(true));
std::auto_ptr<ObjectAnimation> anim(new ObjectAnimation(ptr, mesh, mIsStatic));
Ogre::AxisAlignedBox bounds = anim->getWorldBounds();
Ogre::Vector3 extents = bounds.getSize();
extents *= insert->getScale();
float size = std::max(std::max(extents.x, extents.y), extents.z);
bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && Settings::Manager::getBool("limit small object distance", "Viewing distance");
bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) &&
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;
@ -148,40 +147,10 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool
mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL;
mBounds[ptr.getCell()].merge(bounds);
bool anyTransparency = false;
for(size_t i = 0;!anyTransparency && i < objects.mEntities.size();i++)
{
Ogre::Entity *ent = objects.mEntities[i];
for(unsigned int i=0;!anyTransparency && i < ent->getNumSubEntities(); ++i)
{
anyTransparency = ent->getSubEntity(i)->getMaterial()->isTransparent();
}
}
if(ptr.getTypeName() == typeid(ESM::Light).name())
anim->addLight(ptr.get<ESM::Light>()->mBase);
if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") ||
anyTransparency || !objects.mParticles.empty() || !objects.mLights.empty())
{
for(size_t i = 0;i < objects.mEntities.size();i++)
{
Ogre::Entity *ent = objects.mEntities[i];
for(unsigned int i=0; i < ent->getNumSubEntities(); ++i)
{
Ogre::SubEntity* subEnt = ent->getSubEntity(i);
subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main);
}
ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0);
ent->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc);
}
for(size_t i = 0;i < objects.mParticles.size();i++)
{
Ogre::ParticleSystem *part = objects.mParticles[i];
// TODO: Check the particle system's material for actual transparency
part->setRenderQueueGroup(RQG_Alpha);
part->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0);
part->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc);
}
}
else
if(mIsStatic && Settings::Manager::getBool("use static geometry", "Objects") && anim->canBatch())
{
Ogre::StaticGeometry* sg = 0;
@ -202,7 +171,6 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool
{
if(mStaticGeometry.find(ptr.getCell()) == mStaticGeometry.end())
{
uniqueID = uniqueID+1;
sg = mRenderer.getScene()->createStaticGeometry("sg" + Ogre::StringConverter::toString(uniqueID));
mStaticGeometry[ptr.getCell()] = sg;
@ -225,113 +193,29 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool
sg->setRenderQueueGroup(RQG_Main);
std::vector<Ogre::Entity*>::reverse_iterator iter = objects.mEntities.rbegin();
while(iter != objects.mEntities.rend())
{
Ogre::Node *node = (*iter)->getParentNode();
sg->addEntity(*iter, node->_getDerivedPosition(), node->_getDerivedOrientation(), node->_getDerivedScale());
(*iter)->detachFromParent();
mRenderer.getScene()->destroyEntity(*iter);
++iter;
}
anim->fillBatch(sg);
/* TODO: We could hold on to this and just detach it from the scene graph, so if the Ptr
* ever needs to modify we can reattach it and rebuild the StaticGeometry object without
* it. Would require associating the Ptr with the StaticGeometry. */
anim.reset();
}
if (light)
{
insertLight(ptr, objects.mSkelBase, bounds.getCenter() - insert->_getDerivedPosition());
}
}
void Objects::insertLight (const MWWorld::Ptr& ptr, Ogre::Entity* skelBase, Ogre::Vector3 fallbackCenter)
{
Ogre::SceneNode* insert = mRenderer.getScene()->getSceneNode(ptr.getRefData().getHandle());
assert(insert);
MWWorld::LiveCellRef<ESM::Light> *ref = ptr.get<ESM::Light>();
const int color = ref->mBase->mData.mColor;
const float r = ((color >> 0) & 0xFF) / 255.0f;
const float g = ((color >> 8) & 0xFF) / 255.0f;
const float b = ((color >> 16) & 0xFF) / 255.0f;
const float radius = float (ref->mBase->mData.mRadius);
Ogre::Light *light = mRenderer.getScene()->createLight();
light->setDiffuseColour (r, g, b);
LightInfo info;
info.name = light->getName();
info.radius = radius;
info.colour = Ogre::ColourValue(r, g, b);
if (ref->mBase->mData.mFlags & ESM::Light::Negative)
info.colour *= -1;
info.interior = !ptr.getCell()->mCell->isExterior();
if (ref->mBase->mData.mFlags & ESM::Light::Flicker)
info.type = LT_Flicker;
else if (ref->mBase->mData.mFlags & ESM::Light::FlickerSlow)
info.type = LT_FlickerSlow;
else if (ref->mBase->mData.mFlags & ESM::Light::Pulse)
info.type = LT_Pulse;
else if (ref->mBase->mData.mFlags & ESM::Light::PulseSlow)
info.type = LT_PulseSlow;
else
info.type = LT_Normal;
// randomize lights animations
info.time = Ogre::Math::RangeRandom(-500, +500);
info.phase = Ogre::Math::RangeRandom(-500, +500);
bool quadratic = lightOutQuadInLin() ? !info.interior : lightQuadratic();
// with the standard 1 / (c + d*l + d*d*q) equation the attenuation factor never becomes zero,
// so we ignore lights if their attenuation falls below this factor.
const float threshold = 0.03;
if (!quadratic)
{
float r = radius * lightLinearRadiusMult();
float attenuation = lightLinearValue() / r;
float activationRange = 1 / (threshold * attenuation);
light->setAttenuation(activationRange, 0, attenuation, 0);
}
else
{
float r = radius * lightQuadraticRadiusMult();
float attenuation = lightQuadraticValue() / std::pow(r, 2);
float activationRange = std::sqrt(1 / (threshold * attenuation));
light->setAttenuation(activationRange, 0, 0, attenuation);
}
// If there's an AttachLight bone, attach the light to that, otherwise attach it to the base scene node
if (skelBase && skelBase->getSkeleton ()->hasBone ("AttachLight"))
{
skelBase->attachObjectToBone ("AttachLight", light);
}
else
{
Ogre::SceneNode* childNode = insert->createChildSceneNode (fallbackCenter);
childNode->attachObject(light);
}
mLights.push_back(info);
if(anim.get() != NULL)
mObjects.insert(std::make_pair(ptr, anim.release()));
}
bool Objects::deleteObject (const MWWorld::Ptr& ptr)
{
if (Ogre::SceneNode *base = ptr.getRefData().getBaseNode())
{
Ogre::SceneNode *parent = base->getParentSceneNode();
if(!ptr.getRefData().getBaseNode())
return true;
for (std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *>::const_iterator iter (
mCellSceneNodes.begin()); iter!=mCellSceneNodes.end(); ++iter)
if (iter->second==parent)
PtrAnimationMap::iterator iter = mObjects.find(ptr);
if(iter != mObjects.end())
{
clearSceneNode (base);
base->removeAndDestroyAllChildren();
mRenderer.getScene()->destroySceneNode (base);
delete iter->second;
mObjects.erase(iter);
mRenderer.getScene()->destroySceneNode(ptr.getRefData().getBaseNode());
ptr.getRefData().setBaseNode(0);
return true;
}
@ -339,41 +223,45 @@ bool Objects::deleteObject (const MWWorld::Ptr& ptr)
return false;
}
return true;
}
void Objects::removeCell(MWWorld::Ptr::CellStore* store)
{
if(mCellSceneNodes.find(store) != mCellSceneNodes.end())
for(PtrAnimationMap::iterator iter = mObjects.begin();iter != mObjects.end();)
{
Ogre::SceneNode* base = mCellSceneNodes[store];
for (int i=0; i<base->numChildren(); ++i)
clearSceneNode (static_cast<Ogre::SceneNode *> (base->getChild (i)));
base->removeAndDestroyAllChildren();
mCellSceneNodes.erase(store);
mRenderer.getScene()->destroySceneNode(base);
base = 0;
if(iter->first.getCell() == store)
{
delete iter->second;
mObjects.erase(iter++);
}
else
++iter;
}
if(mStaticGeometry.find(store) != mStaticGeometry.end())
std::map<MWWorld::CellStore*,Ogre::StaticGeometry*>::iterator geom = mStaticGeometry.find(store);
if(geom != mStaticGeometry.end())
{
Ogre::StaticGeometry* sg = mStaticGeometry[store];
mStaticGeometry.erase(store);
Ogre::StaticGeometry *sg = geom->second;
mStaticGeometry.erase(geom);
mRenderer.getScene()->destroyStaticGeometry(sg);
sg = 0;
}
if(mStaticGeometrySmall.find(store) != mStaticGeometrySmall.end())
geom = mStaticGeometrySmall.find(store);
if(geom != mStaticGeometrySmall.end())
{
Ogre::StaticGeometry* sg = mStaticGeometrySmall[store];
Ogre::StaticGeometry *sg = geom->second;
mStaticGeometrySmall.erase(store);
mRenderer.getScene()->destroyStaticGeometry(sg);
sg = 0;
}
if(mBounds.find(store) != mBounds.end())
mBounds.erase(store);
std::map<MWWorld::CellStore*,Ogre::SceneNode*>::iterator cell = mCellSceneNodes.find(store);
if(cell != mCellSceneNodes.end())
{
cell->second->removeAndDestroyAllChildren();
mRenderer.getScene()->destroySceneNode(cell->second);
mCellSceneNodes.erase(cell);
}
}
void Objects::buildStaticGeometry(MWWorld::Ptr::CellStore& cell)
@ -397,146 +285,23 @@ Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::Ptr::CellStore* cell)
void Objects::enableLights()
{
std::vector<LightInfo>::iterator it = mLights.begin();
while (it != mLights.end())
{
if (mRootNode->getCreator()->hasLight(it->name))
{
mRootNode->getCreator()->getLight(it->name)->setVisible(true);
++it;
}
else
it = mLights.erase(it);
}
PtrAnimationMap::const_iterator it = mObjects.begin();
for(;it != mObjects.end();it++)
it->second->enableLights(true);
}
void Objects::disableLights()
{
std::vector<LightInfo>::iterator it = mLights.begin();
while (it != mLights.end())
{
if (mRootNode->getCreator()->hasLight(it->name))
{
mRootNode->getCreator()->getLight(it->name)->setVisible(false);
++it;
}
else
it = mLights.erase(it);
}
}
namespace MWRender
{
namespace Pulse
{
static float amplitude (float phase)
{
return sin (phase);
}
}
namespace Flicker
{
static const float fa = 0.785398f;
static const float fb = 1.17024f;
static const float tdo = 0.94f;
static const float tdm = 2.48f;
static const float f [3] = { 1.5708f, 4.18774f, 5.19934f };
static const float o [3] = { 0.804248f, 2.11115f, 3.46832f };
static const float m [3] = { 1.0f, 0.785f, 0.876f };
static const float s = 0.394f;
static const float phase_wavelength = 120.0f * 3.14159265359f / fa;
static float frequency (float x)
{
return tdo + tdm * sin (fa * x);
}
static float amplitude (float x)
{
float v = 0.0f;
for (int i = 0; i < 3; ++i)
v += sin (fb*x*f[i] + o[1])*m[i];
return v * s;
}
}
PtrAnimationMap::const_iterator it = mObjects.begin();
for(;it != mObjects.end();it++)
it->second->enableLights(false);
}
void Objects::update(const float dt)
{
std::vector<LightInfo>::iterator it = mLights.begin();
while (it != mLights.end())
{
if (mRootNode->getCreator()->hasLight(it->name))
{
Ogre::Light* light = mRootNode->getCreator()->getLight(it->name);
float brightness;
float cycle_time;
float time_distortion;
if ((it->type == LT_Pulse) && (it->type == LT_PulseSlow))
{
cycle_time = 2 * Ogre::Math::PI;
time_distortion = 20.0f;
}
else
{
cycle_time = 500.0f;
it->phase = fmod (it->phase + dt, Flicker::phase_wavelength);
time_distortion = Flicker::frequency (it->phase);
}
it->time += it->dir*dt*time_distortion;
if (it->dir > 0 && it->time > +cycle_time)
{
it->dir = -1.0f;
it->time = +2*cycle_time - it->time;
}
if (it->dir < 0 && it->time < -cycle_time)
{
it->dir = +1.0f;
it->time = -2*cycle_time - it->time;
}
static const float fast = 4.0f/1.0f;
static const float slow = 1.0f/1.0f;
// These formulas are just guesswork, but they work pretty well
if (it->type == LT_Normal)
{
// Less than 1/255 light modifier for a constant light:
brightness = (const float)(1.0 + Flicker::amplitude(it->time*slow) / 255.0 );
}
else if (it->type == LT_Flicker)
{
brightness = (const float)(0.75 + Flicker::amplitude(it->time*fast) * 0.25);
}
else if (it->type == LT_FlickerSlow)
{
brightness = (const float)(0.75 + Flicker::amplitude(it->time*slow) * 0.25);
}
else if (it->type == LT_Pulse)
{
brightness = (const float)(1.0 + Pulse::amplitude (it->time*fast) * 0.25);
}
else if (it->type == LT_PulseSlow)
{
brightness = (const float)(1.0 + Pulse::amplitude (it->time*slow) * 0.25);
}
else
assert(0 && "Invalid light type");
light->setDiffuseColour(it->colour * brightness);
++it;
}
else
it = mLights.erase(it);
}
PtrAnimationMap::const_iterator it = mObjects.begin();
for(;it != mObjects.end();it++)
it->second->runAnimation(dt);
}
void Objects::rebuildStaticGeometry()

@ -15,6 +15,8 @@ namespace MWWorld
namespace MWRender{
class ObjectAnimation;
/// information about light needed for rendering
enum LightType
{
@ -48,15 +50,20 @@ struct LightInfo
};
class Objects{
typedef std::map<MWWorld::Ptr,ObjectAnimation*> PtrAnimationMap;
OEngine::Render::OgreRenderer &mRenderer;
std::map<MWWorld::CellStore*,Ogre::SceneNode*> mCellSceneNodes;
std::map<MWWorld::CellStore*,Ogre::StaticGeometry*> mStaticGeometry;
std::map<MWWorld::CellStore*,Ogre::StaticGeometry*> mStaticGeometrySmall;
std::map<MWWorld::CellStore*,Ogre::AxisAlignedBox> mBounds;
std::vector<LightInfo> mLights;
PtrAnimationMap mObjects;
Ogre::SceneNode* mRootNode;
bool mIsStatic;
static int uniqueID;
MWWorld::Fallback* mFallback;
float lightLinearValue();
float lightLinearRadiusMult();
@ -79,8 +86,7 @@ public:
{}
~Objects(){}
void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool light=false);
void insertLight (const MWWorld::Ptr& ptr, Ogre::Entity *skelBase=0, Ogre::Vector3 fallbackCenter=Ogre::Vector3(0.0f));
void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh);
void enableLights();
void disableLights();

Loading…
Cancel
Save