forked from teamnwah/openmw-tes3coop
Implement NiBillboardNode. Flags not handled yet.
This commit is contained in:
parent
a3ff9e5be8
commit
5931fdcbde
14 changed files with 76 additions and 9 deletions
|
@ -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…
Reference in a new issue