Merge remote-tracking branch 'scrawl/aiming'

sceneinput
Marc Zinnschlag 9 years ago
commit c35ce88ee7

@ -541,6 +541,10 @@ namespace MWBase
virtual void resetActors() = 0;
virtual bool isWalkingOnWater (const MWWorld::Ptr& actor) = 0;
/// Return a vector aiming the actor's weapon towards a target.
/// @note The length of the vector is the distance between actor and target.
virtual osg::Vec3f aimToTarget(const MWWorld::Ptr& actor, const MWWorld::Ptr& target) = 0;
};
}

@ -34,10 +34,9 @@ namespace
return std::atan2(dir.x(), dir.y());
}
float getXAngleToDir(const osg::Vec3f& dir, float dirLen = 0.0f)
float getXAngleToDir(const osg::Vec3f& dir)
{
float len = (dirLen > 0.0f)? dirLen : dir.length();
return -std::asin(dir.z() / len);
return -std::asin(dir.z() / dir.length());
}
const float REACTION_INTERVAL = 0.25f;
@ -346,8 +345,9 @@ namespace MWMechanics
ESM::Position pos = actor.getRefData().getPosition();
osg::Vec3f vActorPos(pos.asVec3());
osg::Vec3f vTargetPos(target.getRefData().getPosition().asVec3());
osg::Vec3f vDirToTarget = vTargetPos - vActorPos;
float distToTarget = vDirToTarget.length();
osg::Vec3f vAimDir = MWBase::Environment::get().getWorld()->aimToTarget(actor, target);
float distToTarget = (vTargetPos - vActorPos).length();
osg::Vec3f& lastActorPos = storage.mLastActorPos;
bool& followTarget = storage.mFollowTarget;
@ -388,7 +388,7 @@ namespace MWMechanics
if (distantCombat)
{
osg::Vec3f& lastTargetPos = storage.mLastTargetPos;
osg::Vec3f vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, REACTION_INTERVAL, weaptype,
vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, REACTION_INTERVAL, weaptype,
storage.mStrength);
lastTargetPos = vTargetPos;
movement.mRotation[0] = getXAngleToDir(vAimDir);
@ -396,8 +396,8 @@ namespace MWMechanics
}
else
{
movement.mRotation[0] = getXAngleToDir(vDirToTarget, distToTarget);
movement.mRotation[2] = getZAngleToDir(vDirToTarget);
movement.mRotation[0] = getXAngleToDir(vAimDir);
movement.mRotation[2] = getZAngleToDir((vTargetPos-vActorPos)); // using vAimDir results in spastic movements since the head is animated
}
// (not quite attack dist while following)
@ -431,19 +431,19 @@ namespace MWMechanics
if(speed == 0.0f) speed = actorClass.getSpeed(actor);
// maximum dist before pit/obstacle for actor to avoid them depending on his speed
float maxAvoidDist = REACTION_INTERVAL * speed + speed / MAX_VEL_ANGULAR_RADIANS * 2; // *2 - for reliability
preferShortcut = checkWayIsClear(vActorPos, vTargetPos, osg::Vec3f(vDirToTarget.x(), vDirToTarget.y(), 0).length() > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2);
preferShortcut = checkWayIsClear(vActorPos, vTargetPos, osg::Vec3f(vAimDir.x(), vAimDir.y(), 0).length() > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2);
}
// don't use pathgrid when actor can move in 3 dimensions
if (canMoveByZ)
{
preferShortcut = true;
movement.mRotation[0] = getXAngleToDir(vDirToTarget, distToTarget);
movement.mRotation[0] = getXAngleToDir(vAimDir);
}
if(preferShortcut)
{
movement.mRotation[2] = getZAngleToDir(vDirToTarget);
movement.mRotation[2] = getZAngleToDir((vTargetPos-vActorPos));
forceNoShortcut = false;
shortcutFailPos.pos[0] = shortcutFailPos.pos[1] = shortcutFailPos.pos[2] = 0;
mPathFinder.clearPath();
@ -478,7 +478,7 @@ namespace MWMechanics
// if there is no new path, then go straight on target
if (!mPathFinder.isPathConstructed())
{
movement.mRotation[2] = getZAngleToDir(vDirToTarget);
movement.mRotation[2] = getZAngleToDir((vTargetPos-vActorPos));
}
}
@ -779,9 +779,8 @@ osg::Vec3f AimDirToMovingTarget(const MWWorld::Ptr& actor, const MWWorld::Ptr& t
// idea: perpendicular to dir to target speed components of target move vector and projectile vector should be the same
osg::Vec3f vActorPos = actor.getRefData().getPosition().asVec3();
osg::Vec3f vTargetPos = target.getRefData().getPosition().asVec3();
osg::Vec3f vDirToTarget = vTargetPos - vActorPos;
osg::Vec3f vDirToTarget = MWBase::Environment::get().getWorld()->aimToTarget(actor, target);
float distToTarget = vDirToTarget.length();
osg::Vec3f vTargetMoveDir = vTargetPos - vLastTargetPos;
@ -812,7 +811,7 @@ osg::Vec3f AimDirToMovingTarget(const MWWorld::Ptr& actor, const MWWorld::Ptr& t
t_collision = projDistDiff / (std::sqrt(projVelDirSquared) - velDir);
else t_collision = 0; // speed of projectile is not enough to reach moving target
return vTargetPos + vTargetMoveDir * t_collision - vActorPos;
return vDirToTarget + vTargetMoveDir * t_collision;
}
}

@ -107,6 +107,7 @@ namespace MWPhysics
bool isOnGround (const MWWorld::Ptr& actor);
/// Get physical half extents (scaled) of the given actor.
osg::Vec3f getHalfExtents(const MWWorld::Ptr& actor);
/// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will

@ -1018,14 +1018,11 @@ namespace MWWorld
return facedObject;
}
std::pair<MWWorld::Ptr,osg::Vec3f> World::getHitContact(const MWWorld::Ptr &ptr, float distance)
osg::Vec3f getActorHeadPosition(const MWWorld::Ptr& actor, MWRender::RenderingManager* rendering)
{
const ESM::Position &posdata = ptr.getRefData().getPosition();
osg::Quat rot = osg::Quat(posdata.rot[0], osg::Vec3f(-1,0,0)) * osg::Quat(posdata.rot[2], osg::Vec3f(0,0,-1));
osg::Vec3f pos (posdata.asVec3());
osg::Vec3f origin(actor.getRefData().getPosition().asVec3());
MWRender::Animation* anim = mRendering->getAnimation(ptr);
MWRender::Animation* anim = rendering->getAnimation(actor);
if (anim != NULL)
{
const osg::Node* node = anim->getNode("Head");
@ -1035,9 +1032,18 @@ namespace MWWorld
{
osg::MatrixList mats = node->getWorldMatrices();
if (mats.size())
pos = mats[0].getTrans();
origin = mats[0].getTrans();
}
}
return origin;
}
std::pair<MWWorld::Ptr,osg::Vec3f> World::getHitContact(const MWWorld::Ptr &ptr, float distance)
{
const ESM::Position &posdata = ptr.getRefData().getPosition();
osg::Quat rot = osg::Quat(posdata.rot[0], osg::Vec3f(-1,0,0)) * osg::Quat(posdata.rot[2], osg::Vec3f(0,0,-1));
osg::Vec3f pos = getActorHeadPosition(ptr, mRendering);
std::pair<MWWorld::Ptr,osg::Vec3f> result = mPhysics->getHitContact(ptr, pos, rot, distance);
if(result.first.isEmpty())
@ -2608,21 +2614,7 @@ namespace MWWorld
MWWorld::Ptr target;
float distance = 192.f; // ??
osg::Vec3f hitPosition = actor.getRefData().getPosition().asVec3();
osg::Vec3f origin(actor.getRefData().getPosition().asVec3());
MWRender::Animation* anim = mRendering->getAnimation(actor);
if (anim != NULL)
{
const osg::Node* node = anim->getNode("Head");
if (node == NULL)
node = anim->getNode("Bip01 Head");
if (node != NULL)
{
osg::MatrixList mats = node->getWorldMatrices();
if (mats.size())
origin = mats[0].getTrans();
}
}
osg::Vec3f origin = getActorHeadPosition(actor, mRendering);
osg::Quat orient = osg::Quat(actor.getRefData().getPosition().rot[0], osg::Vec3f(-1,0,0))
* osg::Quat(actor.getRefData().getPosition().rot[2], osg::Vec3f(0,0,-1));
@ -3262,4 +3254,12 @@ namespace MWWorld
return true;
return false;
}
osg::Vec3f World::aimToTarget(const Ptr &actor, const MWWorld::Ptr& target)
{
osg::Vec3f weaponPos = getActorHeadPosition(actor, mRendering);
osg::Vec3f targetPos = target.getRefData().getPosition().asVec3();
targetPos.z() += mPhysics->getHalfExtents(target).z();
return (targetPos - weaponPos);
}
}

@ -630,6 +630,10 @@ namespace MWWorld
virtual void resetActors();
virtual bool isWalkingOnWater (const MWWorld::Ptr& actor);
/// Return a vector aiming the actor's weapon towards a target.
/// @note The length of the vector is the distance between actor and target.
virtual osg::Vec3f aimToTarget(const MWWorld::Ptr& actor, const MWWorld::Ptr& target);
};
}

Loading…
Cancel
Save