1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-19 10:39:44 +00:00

Don't use xkf if xnif is merely the base model (bug #5371)

This commit is contained in:
Alexei Kotov 2023-01-14 04:36:06 +03:00
parent 4d0788e016
commit 434b4deda1
11 changed files with 35 additions and 29 deletions

View file

@ -6,6 +6,7 @@
Bug #4816: GetWeaponDrawn returns 1 before weapon is attached Bug #4816: GetWeaponDrawn returns 1 before weapon is attached
Bug #5057: Weapon swing sound plays at same pitch whether it hits or misses Bug #5057: Weapon swing sound plays at same pitch whether it hits or misses
Bug #5129: Stuttering animation on Centurion Archer Bug #5129: Stuttering animation on Centurion Archer
Bug #5371: Keyframe animation tracks are used for any file that begins with an X
Bug #5714: Touch spells cast using ExplodeSpell don't always explode Bug #5714: Touch spells cast using ExplodeSpell don't always explode
Bug #5849: Paralysis breaks landing Bug #5849: Paralysis breaks landing
Bug #5883: Immobile creatures don't cause water ripples Bug #5883: Immobile creatures don't cause water ripples

View file

@ -45,7 +45,7 @@ namespace MWClass
{ {
if (!model.empty()) if (!model.empty())
{ {
renderingInterface.getObjects().insertModel(ptr, model, true); renderingInterface.getObjects().insertModel(ptr, model);
ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static); ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static);
} }
} }

View file

@ -108,7 +108,7 @@ namespace MWClass
{ {
if (!model.empty()) if (!model.empty())
{ {
renderingInterface.getObjects().insertModel(ptr, model, true); renderingInterface.getObjects().insertModel(ptr, model);
} }
} }

View file

@ -57,7 +57,7 @@ namespace MWClass
{ {
if (!model.empty()) if (!model.empty())
{ {
renderingInterface.getObjects().insertModel(ptr, model, true); renderingInterface.getObjects().insertModel(ptr, model);
ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static); ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static);
} }
} }

View file

@ -40,8 +40,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Light>* ref = ptr.get<ESM::Light>(); MWWorld::LiveCellRef<ESM::Light>* ref = 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
renderingInterface.getObjects().insertModel( renderingInterface.getObjects().insertModel(ptr, model, !(ref->mBase->mData.mFlags & ESM::Light::OffDefault));
ptr, model, true, !(ref->mBase->mData.mFlags & ESM::Light::OffDefault));
} }
void Light::insertObject(const MWWorld::Ptr& ptr, const std::string& model, const osg::Quat& rotation, void Light::insertObject(const MWWorld::Ptr& ptr, const std::string& model, const osg::Quat& rotation,

View file

@ -23,6 +23,7 @@
#include <components/esm3/loadgmst.hpp> #include <components/esm3/loadgmst.hpp>
#include <components/esm3/loadmgef.hpp> #include <components/esm3/loadmgef.hpp>
#include <components/misc/convert.hpp> #include <components/misc/convert.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/resource/bulletshapemanager.hpp> #include <components/resource/bulletshapemanager.hpp>
#include <components/resource/resourcesystem.hpp> #include <components/resource/resourcesystem.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
@ -642,15 +643,15 @@ namespace MWPhysics
void PhysicsSystem::addActor(const MWWorld::Ptr& ptr, const std::string& mesh) void PhysicsSystem::addActor(const MWWorld::Ptr& ptr, const std::string& mesh)
{ {
osg::ref_ptr<const Resource::BulletShape> shape = mShapeManager->getShape(mesh); std::string animationMesh = Misc::ResourceHelpers::correctActorModelPath(mesh, mResourceSystem->getVFS());
osg::ref_ptr<const Resource::BulletShape> shape = mShapeManager->getShape(animationMesh);
// Try to get shape from basic model as fallback for creatures // Try to get shape from basic model as fallback for creatures
if (!ptr.getClass().isNpc() && shape && shape->mCollisionBox.mExtents.length2() == 0) if (!ptr.getClass().isNpc() && shape && shape->mCollisionBox.mExtents.length2() == 0)
{ {
const std::string fallbackModel = ptr.getClass().getModel(ptr); if (animationMesh != mesh)
if (fallbackModel != mesh)
{ {
shape = mShapeManager->getShape(fallbackModel); shape = mShapeManager->getShape(mesh);
} }
} }

View file

@ -3,6 +3,7 @@
#include <osg/Group> #include <osg/Group>
#include <osg/UserDataContainer> #include <osg/UserDataContainer>
#include <components/misc/resourcehelpers.hpp>
#include <components/sceneutil/positionattitudetransform.hpp> #include <components/sceneutil/positionattitudetransform.hpp>
#include <components/sceneutil/unrefqueue.hpp> #include <components/sceneutil/unrefqueue.hpp>
@ -68,12 +69,21 @@ namespace MWRender
ptr.getRefData().setBaseNode(insert); ptr.getRefData().setBaseNode(insert);
} }
void Objects::insertModel(const MWWorld::Ptr& ptr, const std::string& mesh, bool animated, bool allowLight) void Objects::insertModel(const MWWorld::Ptr& ptr, const std::string& mesh, bool allowLight)
{ {
insertBegin(ptr); insertBegin(ptr);
ptr.getRefData().getBaseNode()->setNodeMask(Mask_Object); ptr.getRefData().getBaseNode()->setNodeMask(Mask_Object);
bool animated = ptr.getClass().useAnim();
std::string animationMesh = mesh;
if (animated && !mesh.empty())
{
animationMesh = Misc::ResourceHelpers::correctActorModelPath(mesh, mResourceSystem->getVFS());
if (animationMesh == mesh)
animated = false;
}
osg::ref_ptr<ObjectAnimation> anim(new ObjectAnimation(ptr, mesh, mResourceSystem, animated, allowLight)); osg::ref_ptr<ObjectAnimation> anim(
new ObjectAnimation(ptr, animationMesh, mResourceSystem, animated, allowLight));
mObjects.emplace(ptr.mRef, std::move(anim)); mObjects.emplace(ptr.mRef, std::move(anim));
} }
@ -83,13 +93,16 @@ namespace MWRender
insertBegin(ptr); insertBegin(ptr);
ptr.getRefData().getBaseNode()->setNodeMask(Mask_Actor); ptr.getRefData().getBaseNode()->setNodeMask(Mask_Actor);
std::string animationMesh = Misc::ResourceHelpers::correctActorModelPath(mesh, mResourceSystem->getVFS());
// FIXME: if animationMesh == mesh, the creature shouldn't be animated
// CreatureAnimation // CreatureAnimation
osg::ref_ptr<Animation> anim; osg::ref_ptr<Animation> anim;
if (weaponsShields) if (weaponsShields)
anim = new CreatureWeaponAnimation(ptr, mesh, mResourceSystem); anim = new CreatureWeaponAnimation(ptr, animationMesh, mResourceSystem);
else else
anim = new CreatureAnimation(ptr, mesh, mResourceSystem); anim = new CreatureAnimation(ptr, animationMesh, mResourceSystem);
if (mObjects.emplace(ptr.mRef, anim).second) if (mObjects.emplace(ptr.mRef, anim).second)
ptr.getClass().getContainerStore(ptr).setContListener(static_cast<ActorAnimation*>(anim.get())); ptr.getClass().getContainerStore(ptr).setContListener(static_cast<ActorAnimation*>(anim.get()));

View file

@ -72,10 +72,8 @@ namespace MWRender
SceneUtil::UnrefQueue& unrefQueue); SceneUtil::UnrefQueue& unrefQueue);
~Objects(); ~Objects();
/// @param animated Attempt to load separate keyframes from a .kf file matching the model file?
/// @param allowLight If false, no lights will be created, and particles systems will be removed. /// @param allowLight If false, no lights will be created, and particles systems will be removed.
void insertModel( void insertModel(const MWWorld::Ptr& ptr, const std::string& model, bool allowLight = true);
const MWWorld::Ptr& ptr, const std::string& model, bool animated = false, bool allowLight = true);
void insertNPC(const MWWorld::Ptr& ptr); void insertNPC(const MWWorld::Ptr& ptr);
void insertCreature(const MWWorld::Ptr& ptr, const std::string& model, bool weaponsShields); void insertCreature(const MWWorld::Ptr& ptr, const std::string& model, bool weaponsShields);

View file

@ -90,15 +90,11 @@ namespace
rendering.rotateObject(ptr, rotation); rendering.rotateObject(ptr, rotation);
} }
std::string getModel(const MWWorld::Ptr& ptr, const VFS::Manager* vfs) std::string getModel(const MWWorld::Ptr& ptr)
{ {
if (Misc::ResourceHelpers::isHiddenMarker(ptr.getCellRef().getRefId())) if (Misc::ResourceHelpers::isHiddenMarker(ptr.getCellRef().getRefId()))
return {}; return {};
bool useAnim = ptr.getClass().useAnim(); return ptr.getClass().getModel(ptr);
std::string model = ptr.getClass().getModel(ptr);
if (useAnim)
model = Misc::ResourceHelpers::correctActorModelPath(model, vfs);
return model;
} }
void addObject(const MWWorld::Ptr& ptr, const MWWorld::World& world, const std::vector<ESM::RefNum>& pagedRefs, void addObject(const MWWorld::Ptr& ptr, const MWWorld::World& world, const std::vector<ESM::RefNum>& pagedRefs,
@ -110,7 +106,7 @@ namespace
return; return;
} }
std::string model = getModel(ptr, rendering.getResourceSystem()->getVFS()); std::string model = getModel(ptr);
const auto rotation = makeDirectNodeRotation(ptr); const auto rotation = makeDirectNodeRotation(ptr);
const ESM::RefNum& refnum = ptr.getCellRef().getRefNum(); const ESM::RefNum& refnum = ptr.getCellRef().getRefNum();
@ -279,8 +275,7 @@ namespace MWWorld
{ {
if (!ptr.getRefData().getBaseNode()) if (!ptr.getRefData().getBaseNode())
return; return;
ptr.getClass().insertObjectRendering( ptr.getClass().insertObjectRendering(ptr, getModel(ptr), mRendering);
ptr, getModel(ptr, mRendering.getResourceSystem()->getVFS()), mRendering);
setNodeRotation(ptr, mRendering, makeNodeRotation(ptr, RotationOrder::direct)); setNodeRotation(ptr, mRendering, makeNodeRotation(ptr, RotationOrder::direct));
reloadTerrain(); reloadTerrain();
} }
@ -630,7 +625,7 @@ namespace MWWorld
ptr.mRef->mData.mPhysicsPostponed = false; ptr.mRef->mData.mPhysicsPostponed = false;
if (ptr.mRef->mData.isEnabled() && ptr.mRef->mData.getCount() > 0) if (ptr.mRef->mData.isEnabled() && ptr.mRef->mData.getCount() > 0)
{ {
std::string model = getModel(ptr, MWBase::Environment::get().getResourceSystem()->getVFS()); std::string model = getModel(ptr);
if (!model.empty()) if (!model.empty())
{ {
const auto rotation = makeNodeRotation(ptr, RotationOrder::direct); const auto rotation = makeNodeRotation(ptr, RotationOrder::direct);

View file

@ -2430,10 +2430,8 @@ namespace MWWorld
MWBase::Environment::get().getMechanicsManager()->add(getPlayerPtr()); MWBase::Environment::get().getMechanicsManager()->add(getPlayerPtr());
MWBase::Environment::get().getWindowManager()->watchActor(getPlayerPtr()); MWBase::Environment::get().getWindowManager()->watchActor(getPlayerPtr());
std::string model = getPlayerPtr().getClass().getModel(getPlayerPtr());
model = Misc::ResourceHelpers::correctActorModelPath(model, mResourceSystem->getVFS());
mPhysics->remove(getPlayerPtr()); mPhysics->remove(getPlayerPtr());
mPhysics->addActor(getPlayerPtr(), model); mPhysics->addActor(getPlayerPtr(), getPlayerPtr().getClass().getModel(getPlayerPtr()));
applyLoopingParticles(player); applyLoopingParticles(player);

View file

@ -208,6 +208,7 @@ namespace NifBullet
} }
// files with the name convention xmodel.nif usually have keyframes stored in a separate file xmodel.kf (see // files with the name convention xmodel.nif usually have keyframes stored in a separate file xmodel.kf (see
// Animation::addAnimSource). assume all nodes in the file will be animated // Animation::addAnimSource). assume all nodes in the file will be animated
// TODO: investigate whether this should and could be optimized.
const bool isAnimated = pathFileNameStartsWithX(filename); const bool isAnimated = pathFileNameStartsWithX(filename);
// If there's no bounding box, we'll have to generate a Bullet collision shape // If there's no bounding box, we'll have to generate a Bullet collision shape