Implement NiBillboardNode. Flags not handled yet.

actorid
scrawl 11 years ago
parent a3ff9e5be8
commit 5931fdcbde

@ -150,9 +150,12 @@ void Actors::removeCell(MWWorld::Ptr::CellStore* store)
}
}
void Actors::update (float duration)
void Actors::update (Ogre::Camera* camera)
{
// Nothing to do
for(PtrAnimationMap::iterator iter = mAllActors.begin();iter != mAllActors.end(); ++iter)
{
iter->second->preRender(camera);
}
}
Animation* Actors::getAnimation(const MWWorld::Ptr &ptr)

@ -47,7 +47,7 @@ namespace MWRender
void removeCell(MWWorld::CellStore* store);
void update (float duration);
void update (Ogre::Camera* camera);
/// Updates containing cell for object rendering data
void updateObjectCell(const MWWorld::Ptr &old, const MWWorld::Ptr &cur);

@ -1117,6 +1117,16 @@ void Animation::updateEffects(float duration)
}
}
void Animation::preRender(Ogre::Camera *camera)
{
for (std::vector<EffectParams>::iterator it = mEffects.begin(); it != mEffects.end(); ++it)
{
NifOgre::ObjectScenePtr objects = it->mObjects;
objects->rotateBillboardNodes(camera);
}
mObjectRoot->rotateBillboardNodes(camera);
}
// TODO: Should not be here
Ogre::Vector3 Animation::getEnchantmentColor(MWWorld::Ptr item)
{
@ -1180,6 +1190,8 @@ bool ObjectAnimation::canBatch() const
{
if(!mObjectRoot->mParticles.empty() || !mObjectRoot->mLights.empty() || !mObjectRoot->mControllers.empty())
return false;
if (!mObjectRoot->mBillboardNodes.empty())
return false;
return std::find_if(mObjectRoot->mEntities.begin(), mObjectRoot->mEntities.end(),
FindEntityTransparency()) == mObjectRoot->mEntities.end();
}

@ -216,6 +216,9 @@ public:
void removeEffect (int effectId);
void getLoopingEffects (std::vector<int>& out);
/// Prepare this animation for being rendered with \a camera (rotates billboard nodes)
virtual void preRender (Ogre::Camera* camera);
virtual void setAlpha(float alpha) {}
private:
void updateEffects(float duration);

@ -730,6 +730,17 @@ void NpcAnimation::setAlpha(float alpha)
}
}
void NpcAnimation::preRender(Ogre::Camera *camera)
{
Animation::preRender(camera);
for (int i=0; i<ESM::PRT_Count; ++i)
{
if (mObjectParts[i].isNull())
continue;
mObjectParts[i]->rotateBillboardNodes(camera);
}
}
void NpcAnimation::applyAlpha(float alpha, Ogre::Entity *ent, NifOgre::ObjectScenePtr scene)
{
ent->getSubEntity(0)->setRenderQueueGroup(alpha != 1.f || ent->getSubEntity(0)->getMaterial()->isTransparent()

@ -116,6 +116,9 @@ public:
/// Make the NPC only partially visible
virtual void setAlpha(float alpha);
/// Prepare this animation for being rendered with \a camera (rotates billboard nodes)
virtual void preRender (Ogre::Camera* camera);
};
}

@ -245,11 +245,16 @@ void Objects::disableLights()
it->second->enableLights(false);
}
void Objects::update(const float dt)
void Objects::update(float dt, Ogre::Camera* camera)
{
PtrAnimationMap::const_iterator it = mObjects.begin();
for(;it != mObjects.end();it++)
it->second->runAnimation(dt);
it = mObjects.begin();
for(;it != mObjects.end();it++)
it->second->preRender(camera);
}
void Objects::rebuildStaticGeometry()

@ -48,7 +48,7 @@ public:
void enableLights();
void disableLights();
void update (const float dt);
void update (float dt, Ogre::Camera* camera);
///< per-frame update
Ogre::AxisAlignedBox getDimensions(MWWorld::CellStore*);

@ -372,9 +372,9 @@ void RenderingManager::update (float duration, bool paused)
if(paused)
return;
mActors->update (duration);
mObjects->update (duration);
mActors->update (mRendering.getCamera());
mPlayerAnimation->preRender(mRendering.getCamera());
mObjects->update (duration, mRendering.getCamera());
mSkyManager->update(duration);

@ -210,7 +210,7 @@ static const RecordFactoryEntry recordFactories [] = {
{ "AvoidNode", &construct <NiNode >, RC_AvoidNode },
{ "NiBSParticleNode", &construct <NiNode >, RC_NiBSParticleNode },
{ "NiBSAnimationNode", &construct <NiNode >, RC_NiBSAnimationNode },
{ "NiBillboardNode", &construct <NiNode >, RC_NiNode },
{ "NiBillboardNode", &construct <NiNode >, RC_NiBillboardNode },
{ "NiTriShape", &construct <NiTriShape >, RC_NiTriShape },
{ "NiRotatingParticles", &construct <NiRotatingParticles >, RC_NiRotatingParticles },
{ "NiAutoNormalParticles", &construct <NiAutoNormalParticles >, RC_NiAutoNormalParticles },

@ -36,6 +36,7 @@ enum RecordType
{
RC_MISSING = 0,
RC_NiNode,
RC_NiBillboardNode,
RC_AvoidNode,
RC_NiTriShape,
RC_NiRotatingParticles,

@ -110,6 +110,17 @@ ObjectScene::~ObjectScene()
mSkelBase = NULL;
}
void ObjectScene::rotateBillboardNodes(Ogre::Camera *camera)
{
for (std::vector<Ogre::Node*>::iterator it = mBillboardNodes.begin(); it != mBillboardNodes.end(); ++it)
{
assert(mSkelBase);
Ogre::Node* node = *it;
node->_setDerivedOrientation(mSkelBase->getParentNode()->_getDerivedOrientation().Inverse() *
camera->getRealOrientation());
}
}
// Animates a texture
class FlipController
{
@ -1007,6 +1018,17 @@ class NIFObjectLoader
else
flags |= node->flags;
if (node->recType == Nif::RC_NiBillboardNode)
{
// TODO: figure out what the flags mean.
// NifSkope has names for them, but doesn't implement them.
// Change mBillboardNodes to map <Bone, billboard type>
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, node->recIndex);
Ogre::Bone* bone = scene->mSkelBase->getSkeleton()->getBone(trgtid);
bone->setManuallyControlled(true);
scene->mBillboardNodes.push_back(bone);
}
Nif::ExtraPtr e = node->extra;
while(!e.empty())
{

@ -61,6 +61,9 @@ struct ObjectScene {
std::vector<Ogre::ParticleSystem*> mParticles;
std::vector<Ogre::Light*> mLights;
// Nodes that should always face the camera when rendering
std::vector<Ogre::Node*> mBillboardNodes;
Ogre::SceneManager* mSceneMgr;
// The maximum length on any of the controllers. For animations with controllers, but no text keys, consider this the animation length.
@ -76,6 +79,9 @@ struct ObjectScene {
{ }
~ObjectScene();
// Rotate nodes in mBillboardNodes so they face the given camera
void rotateBillboardNodes(Ogre::Camera* camera);
};
typedef Ogre::SharedPtr<ObjectScene> ObjectScenePtr;

@ -30,6 +30,7 @@ void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node,
node->recType == Nif::RC_RootCollisionNode || /* handled in nifbullet (hopefully) */
node->recType == Nif::RC_NiTriShape || /* Handled in the mesh loader */
node->recType == Nif::RC_NiBSAnimationNode || /* Handled in the object loader */
node->recType == Nif::RC_NiBillboardNode || /* Handled in the object loader */
node->recType == Nif::RC_NiBSParticleNode ||
node->recType == Nif::RC_NiCamera ||
node->recType == Nif::RC_NiAutoNormalParticles ||

Loading…
Cancel
Save