Use the correct scale for actor swim height (Fixes #2833)

This commit is contained in:
scrawl 2015-11-01 21:45:58 +01:00
parent 819fecd08e
commit bd9dc58560
13 changed files with 48 additions and 14 deletions

View File

@ -774,7 +774,7 @@ namespace MWClass
return ref->mBase->mAiData.mFight; return ref->mBase->mAiData.mFight;
} }
void Creature::adjustScale(const MWWorld::Ptr &ptr, osg::Vec3f &scale) const void Creature::adjustScale(const MWWorld::Ptr &ptr, osg::Vec3f &scale, bool /* rendering */) const
{ {
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>(); MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
scale *= ref->mBase->mScale; scale *= ref->mBase->mScale;

View File

@ -133,7 +133,8 @@ namespace MWClass
virtual int getBaseFightRating(const MWWorld::Ptr &ptr) const; virtual int getBaseFightRating(const MWWorld::Ptr &ptr) const;
virtual void adjustScale(const MWWorld::Ptr& ptr, osg::Vec3f& scale) const; virtual void adjustScale(const MWWorld::Ptr& ptr, osg::Vec3f& scale, bool rendering) const;
/// @param rendering Indicates if the scale to adjust is for the rendering mesh, or for the collision mesh
}; };
} }

View File

@ -1012,8 +1012,12 @@ namespace MWClass
+ shield; + shield;
} }
void Npc::adjustScale(const MWWorld::Ptr &ptr, osg::Vec3f&scale) const void Npc::adjustScale(const MWWorld::Ptr &ptr, osg::Vec3f&scale, bool rendering) const
{ {
if (!rendering)
return; // collision meshes are not scaled based on race height
// having the same collision extents for all races makes the environments easier to test
MWWorld::LiveCellRef<ESM::NPC> *ref = MWWorld::LiveCellRef<ESM::NPC> *ref =
ptr.get<ESM::NPC>(); ptr.get<ESM::NPC>();

View File

@ -109,7 +109,8 @@ namespace MWClass
/// \param actor Actor that is resposible for the ID being applied to \a ptr. /// \param actor Actor that is resposible for the ID being applied to \a ptr.
/// \return Any effect? /// \return Any effect?
virtual void adjustScale (const MWWorld::Ptr &ptr, osg::Vec3f &scale) const; virtual void adjustScale (const MWWorld::Ptr &ptr, osg::Vec3f &scale, bool rendering) const;
/// @param rendering Indicates if the scale to adjust is for the rendering mesh, or for the collision mesh
virtual void skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType, float extraFactor=1.f) const; virtual void skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType, float extraFactor=1.f) const;
///< Inform actor \a ptr that a skill use has succeeded. ///< Inform actor \a ptr that a skill use has succeeded.

View File

@ -110,12 +110,14 @@ void Actor::updateScale()
float scale = mPtr.getCellRef().getScale(); float scale = mPtr.getCellRef().getScale();
osg::Vec3f scaleVec(scale,scale,scale); osg::Vec3f scaleVec(scale,scale,scale);
if (!mPtr.getClass().isNpc()) mPtr.getClass().adjustScale(mPtr, scaleVec, false);
mPtr.getClass().adjustScale(mPtr, scaleVec);
mScale = scaleVec; mScale = scaleVec;
mShape->setLocalScaling(toBullet(mScale)); mShape->setLocalScaling(toBullet(mScale));
scaleVec = osg::Vec3f(scale,scale,scale);
mPtr.getClass().adjustScale(mPtr, scaleVec, true);
mRenderingScale = scaleVec;
updatePosition(); updatePosition();
} }
@ -124,6 +126,11 @@ osg::Vec3f Actor::getHalfExtents() const
return osg::componentMultiply(mHalfExtents, mScale); return osg::componentMultiply(mHalfExtents, mScale);
} }
osg::Vec3f Actor::getRenderingHalfExtents() const
{
return osg::componentMultiply(mHalfExtents, mRenderingScale);
}
void Actor::setInertialForce(const osg::Vec3f &force) void Actor::setInertialForce(const osg::Vec3f &force)
{ {
mForce = force; mForce = force;

View File

@ -66,10 +66,17 @@ namespace MWPhysics
void updatePosition(); void updatePosition();
/** /**
* Returns the (scaled) half extents * Returns the half extents of the collision body (scaled according to collision scale)
*/ */
osg::Vec3f getHalfExtents() const; osg::Vec3f getHalfExtents() const;
/**
* Returns the half extents of the collision body (scaled according to rendering scale)
* @note The reason we need this extra method is because of an inconsistency in MW - NPC race scales aren't applied to the collision shape,
* most likely to make environment collision testing easier. However in some cases (swimming level) we want the actual scale.
*/
osg::Vec3f getRenderingHalfExtents() const;
/** /**
* Sets the current amount of inertial force (incl. gravity) affecting this physic actor * Sets the current amount of inertial force (incl. gravity) affecting this physic actor
*/ */
@ -118,6 +125,7 @@ namespace MWPhysics
osg::Quat mRotation; osg::Quat mRotation;
osg::Vec3f mScale; osg::Vec3f mScale;
osg::Vec3f mRenderingScale;
osg::Vec3f mPosition; osg::Vec3f mPosition;
osg::Vec3f mForce; osg::Vec3f mForce;

View File

@ -261,7 +261,7 @@ namespace MWPhysics
static const float fSwimHeightScale = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>() static const float fSwimHeightScale = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fSwimHeightScale")->getFloat(); .find("fSwimHeightScale")->getFloat();
float swimlevel = waterlevel + halfExtents.z() - (halfExtents.z() * 2 * fSwimHeightScale); float swimlevel = waterlevel + halfExtents.z() - (physicActor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale);
ActorTracer tracer; ActorTracer tracer;
osg::Vec3f inertia = physicActor->getInertialForce(); osg::Vec3f inertia = physicActor->getInertialForce();
@ -878,6 +878,15 @@ namespace MWPhysics
return osg::Vec3f(); return osg::Vec3f();
} }
osg::Vec3f PhysicsSystem::getRenderingHalfExtents(const MWWorld::Ptr &actor)
{
Actor* physactor = getActor(actor);
if (physactor)
return physactor->getRenderingHalfExtents();
else
return osg::Vec3f();
}
class ContactTestResultCallback : public btCollisionWorld::ContactResultCallback class ContactTestResultCallback : public btCollisionWorld::ContactResultCallback
{ {
public: public:

View File

@ -110,6 +110,9 @@ namespace MWPhysics
/// Get physical half extents (scaled) of the given actor. /// Get physical half extents (scaled) of the given actor.
osg::Vec3f getHalfExtents(const MWWorld::Ptr& actor); osg::Vec3f getHalfExtents(const MWWorld::Ptr& actor);
/// @see MWPhysics::Actor::getRenderingHalfExtents
osg::Vec3f getRenderingHalfExtents(const MWWorld::Ptr& actor);
/// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will /// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will
/// be overwritten. Valid until the next call to applyQueuedMovement. /// be overwritten. Valid until the next call to applyQueuedMovement.
void queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity); void queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity);

View File

@ -287,7 +287,7 @@ namespace MWRender
void InventoryPreview::onSetup() void InventoryPreview::onSetup()
{ {
osg::Vec3f scale (1.f, 1.f, 1.f); osg::Vec3f scale (1.f, 1.f, 1.f);
mCharacter.getClass().adjustScale(mCharacter, scale); mCharacter.getClass().adjustScale(mCharacter, scale, true);
mNode->setScale(scale); mNode->setScale(scale);

View File

@ -287,7 +287,7 @@ namespace MWWorld
return ""; return "";
} }
void Class::adjustScale(const MWWorld::Ptr& ptr, osg::Vec3f& scale) const void Class::adjustScale(const MWWorld::Ptr& ptr, osg::Vec3f& scale, bool rendering) const
{ {
} }

View File

@ -258,7 +258,8 @@ namespace MWWorld
virtual int getEnchantmentPoints (const MWWorld::Ptr& ptr) const; virtual int getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
///< @return the number of enchantment points available for possible enchanting ///< @return the number of enchantment points available for possible enchanting
virtual void adjustScale(const MWWorld::Ptr& ptr, osg::Vec3f& scale) const; virtual void adjustScale(const MWWorld::Ptr& ptr, osg::Vec3f& scale, bool rendering) const;
/// @param rendering Indicates if the scale to adjust is for the rendering mesh, or for the collision mesh
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const; virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
///< Determine whether or not \a item can be sold to an npc with the given \a npcServices ///< Determine whether or not \a item can be sold to an npc with the given \a npcServices

View File

@ -72,7 +72,7 @@ namespace
{ {
float scale = ptr.getCellRef().getScale(); float scale = ptr.getCellRef().getScale();
osg::Vec3f scaleVec (scale, scale, scale); osg::Vec3f scaleVec (scale, scale, scale);
ptr.getClass().adjustScale(ptr, scaleVec); ptr.getClass().adjustScale(ptr, scaleVec, true);
rendering.scaleObject(ptr, scaleVec); rendering.scaleObject(ptr, scaleVec);
} }
} }

View File

@ -1969,7 +1969,7 @@ namespace MWWorld
{ {
osg::Vec3f pos (object.getRefData().getPosition().asVec3()); osg::Vec3f pos (object.getRefData().getPosition().asVec3());
pos.z() += heightRatio*2*mPhysics->getHalfExtents(object).z(); pos.z() += heightRatio*2*mPhysics->getRenderingHalfExtents(object).z();
return isUnderwater(object.getCell(), pos); return isUnderwater(object.getCell(), pos);
} }