Various math code ported to osg

This commit is contained in:
scrawl 2015-06-03 19:41:19 +02:00
parent 0cc9b1bb40
commit 7bacb9418d
28 changed files with 180 additions and 177 deletions

View file

@ -11,14 +11,6 @@
#include "../mwrender/rendermode.hpp" #include "../mwrender/rendermode.hpp"
namespace Ogre
{
class Vector2;
class Vector3;
class Quaternion;
class Image;
}
namespace osg namespace osg
{ {
class Vec3f; class Vec3f;
@ -423,7 +415,7 @@ namespace MWBase
virtual bool getLOS(const MWWorld::Ptr& actor,const MWWorld::Ptr& targetActor) = 0; virtual bool getLOS(const MWWorld::Ptr& actor,const MWWorld::Ptr& targetActor) = 0;
///< get Line of Sight (morrowind stupid implementation) ///< get Line of Sight (morrowind stupid implementation)
virtual float getDistToNearestRayHit(const Ogre::Vector3& from, const Ogre::Vector3& dir, float maxDist) = 0; virtual float getDistToNearestRayHit(const osg::Vec3f& from, const osg::Vec3f& dir, float maxDist) = 0;
virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable) = 0; virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable) = 0;
@ -497,7 +489,7 @@ namespace MWBase
// Are we in an exterior or pseudo-exterior cell and it's night? // Are we in an exterior or pseudo-exterior cell and it's night?
virtual bool isDark() const = 0; virtual bool isDark() const = 0;
virtual bool findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, Ogre::Vector3& result) = 0; virtual bool findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, osg::Vec3f& result) = 0;
/// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker) /// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)
/// @note id must be lower case /// @note id must be lower case

View file

@ -580,10 +580,10 @@ namespace MWClass
return dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData()).mMovement; return dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData()).mMovement;
} }
Ogre::Vector3 Creature::getRotationVector (const MWWorld::Ptr& ptr) const osg::Vec3f Creature::getRotationVector (const MWWorld::Ptr& ptr) const
{ {
MWMechanics::Movement &movement = getMovementSettings(ptr); MWMechanics::Movement &movement = getMovementSettings(ptr);
Ogre::Vector3 vec(movement.mRotation); osg::Vec3f vec(movement.mRotation[0], movement.mRotation[1], movement.mRotation[2]);
movement.mRotation[0] = 0.0f; movement.mRotation[0] = 0.0f;
movement.mRotation[1] = 0.0f; movement.mRotation[1] = 0.0f;
movement.mRotation[2] = 0.0f; movement.mRotation[2] = 0.0f;

View file

@ -113,7 +113,7 @@ namespace MWClass
virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const; virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const;
///< Return desired movement. ///< Return desired movement.
virtual Ogre::Vector3 getRotationVector (const MWWorld::Ptr& ptr) const; virtual osg::Vec3f getRotationVector (const MWWorld::Ptr& ptr) const;
///< Return desired rotations, as euler angles. ///< Return desired rotations, as euler angles.
float getSpeed (const MWWorld::Ptr& ptr) const; float getSpeed (const MWWorld::Ptr& ptr) const;

View file

@ -961,10 +961,10 @@ namespace MWClass
return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mMovement; return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mMovement;
} }
Ogre::Vector3 Npc::getRotationVector (const MWWorld::Ptr& ptr) const osg::Vec3f Npc::getRotationVector (const MWWorld::Ptr& ptr) const
{ {
MWMechanics::Movement &movement = getMovementSettings(ptr); MWMechanics::Movement &movement = getMovementSettings(ptr);
Ogre::Vector3 vec(movement.mRotation); osg::Vec3f vec(movement.mRotation[0], movement.mRotation[1], movement.mRotation[2]);
movement.mRotation[0] = 0.0f; movement.mRotation[0] = 0.0f;
movement.mRotation[1] = 0.0f; movement.mRotation[1] = 0.0f;
movement.mRotation[2] = 0.0f; movement.mRotation[2] = 0.0f;

View file

@ -105,7 +105,7 @@ namespace MWClass
virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const; virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const;
///< Return desired movement. ///< Return desired movement.
virtual Ogre::Vector3 getRotationVector (const MWWorld::Ptr& ptr) const; virtual osg::Vec3f getRotationVector (const MWWorld::Ptr& ptr) const;
///< Return desired rotations, as euler angles. ///< Return desired rotations, as euler angles.
virtual float getCapacity (const MWWorld::Ptr& ptr) const; virtual float getCapacity (const MWWorld::Ptr& ptr) const;

View file

@ -394,7 +394,7 @@ namespace MWGui
} }
if (mIsDrowning) if (mIsDrowning)
mDrowningFlashTheta += dt * Ogre::Math::TWO_PI; mDrowningFlashTheta += dt * osg::PI*2;
} }
void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent) void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent)

View file

@ -169,8 +169,7 @@ namespace MWGui
if (!interior) if (!interior)
{ {
ESM::Position playerPos = player.getRefData().getPosition(); ESM::Position playerPos = player.getRefData().getPosition();
float d = Ogre::Vector3(pos.pos[0], pos.pos[1], 0).distance( float d = (osg::Vec3f(pos.pos[0], pos.pos[1], 0) - osg::Vec3f(playerPos.pos[0], playerPos.pos[1], 0)).length();
Ogre::Vector3(playerPos.pos[0], playerPos.pos[1], 0));
int hours = static_cast<int>(d /MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fTravelTimeMult")->getFloat()); int hours = static_cast<int>(d /MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fTravelTimeMult")->getFloat());
for(int i = 0;i < hours;i++) for(int i = 0;i < hours;i++)
{ {

View file

@ -992,12 +992,12 @@ namespace MWGui
mMap->setCellPrefix (cell->getCell()->mName ); mMap->setCellPrefix (cell->getCell()->mName );
mHud->setCellPrefix (cell->getCell()->mName ); mHud->setCellPrefix (cell->getCell()->mName );
Ogre::Vector3 worldPos; osg::Vec3f worldPos;
if (!MWBase::Environment::get().getWorld()->findInteriorPositionInWorldSpace(cell, worldPos)) if (!MWBase::Environment::get().getWorld()->findInteriorPositionInWorldSpace(cell, worldPos))
worldPos = MWBase::Environment::get().getWorld()->getPlayer().getLastKnownExteriorPosition(); worldPos = MWBase::Environment::get().getWorld()->getPlayer().getLastKnownExteriorPosition();
else else
MWBase::Environment::get().getWorld()->getPlayer().setLastKnownExteriorPosition(worldPos); MWBase::Environment::get().getWorld()->getPlayer().setLastKnownExteriorPosition(worldPos);
mMap->setGlobalMapPlayerPosition(worldPos.x, worldPos.y); mMap->setGlobalMapPlayerPosition(worldPos.x(), worldPos.y());
} }
} }

View file

@ -316,7 +316,7 @@ namespace MWMechanics
const ESM::Position& actor1Pos = actor1.getRefData().getPosition(); const ESM::Position& actor1Pos = actor1.getRefData().getPosition();
const ESM::Position& actor2Pos = actor2.getRefData().getPosition(); const ESM::Position& actor2Pos = actor2.getRefData().getPosition();
float sqrDist = Ogre::Vector3(actor1Pos.pos).squaredDistance(Ogre::Vector3(actor2Pos.pos)); float sqrDist = (actor1Pos.asVec3() - actor2Pos.asVec3()).length2();
if (sqrDist > 7168*7168) if (sqrDist > 7168*7168)
return; return;
@ -1081,7 +1081,7 @@ namespace MWMechanics
// AI and magic effects update // AI and magic effects update
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{ {
bool inProcessingRange = Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(iter->first.getRefData().getPosition().pos)) bool inProcessingRange = (player.getRefData().getPosition().asVec3() - iter->first.getRefData().getPosition().asVec3()).length2()
<= sqrProcessingDistance; <= sqrProcessingDistance;
iter->second->getCharacterController()->setActive(inProcessingRange); iter->second->getCharacterController()->setActive(inProcessingRange);
@ -1151,7 +1151,7 @@ namespace MWMechanics
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{ {
if (iter->first != player && if (iter->first != player &&
Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(iter->first.getRefData().getPosition().pos)) (player.getRefData().getPosition().asVec3() - iter->first.getRefData().getPosition().asVec3()).length2()
> sqrProcessingDistance) > sqrProcessingDistance)
continue; continue;
@ -1236,7 +1236,7 @@ namespace MWMechanics
continue; continue;
// is the player in range and can they be detected // is the player in range and can they be detected
if (Ogre::Vector3(iter->first.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(player.getRefData().getPosition().pos)) <= radius*radius if ((iter->first.getRefData().getPosition().asVec3() - player.getRefData().getPosition().asVec3()).length2() <= radius*radius
&& MWBase::Environment::get().getWorld()->getLOS(player, iter->first)) && MWBase::Environment::get().getWorld()->getLOS(player, iter->first))
{ {
if (MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, iter->first)) if (MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, iter->first))

View file

@ -56,7 +56,7 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor, AiState& stat
actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true); actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true);
// Turn away from the door and move when turn completed // Turn away from the door and move when turn completed
if (zTurn(actor, Ogre::Radian(std::atan2(x,y) + mAdjAngle), Ogre::Degree(5))) if (zTurn(actor, std::atan2(x,y) + mAdjAngle, osg::DegreesToRadians(5.f)))
actor.getClass().getMovementSettings(actor).mPosition[1] = 1; actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
else else
actor.getClass().getMovementSettings(actor).mPosition[1] = 0; actor.getClass().getMovementSettings(actor).mPosition[1] = 0;

View file

@ -35,18 +35,18 @@ namespace
void getMinMaxAttackDuration(const MWWorld::Ptr& actor, float (*fMinMaxDurations)[2]); void getMinMaxAttackDuration(const MWWorld::Ptr& actor, float (*fMinMaxDurations)[2]);
Ogre::Vector3 AimDirToMovingTarget(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, const Ogre::Vector3& vLastTargetPos, osg::Vec3f AimDirToMovingTarget(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, const osg::Vec3f& vLastTargetPos,
float duration, int weapType, float strength); float duration, int weapType, float strength);
float getZAngleToDir(const Ogre::Vector3& dir) float getZAngleToDir(const osg::Vec3f& dir)
{ {
return Ogre::Math::ATan2(dir.x,dir.y).valueDegrees(); return osg::RadiansToDegrees(std::atan2(dir.x(), dir.y()));
} }
float getXAngleToDir(const Ogre::Vector3& dir, float dirLen = 0.0f) float getXAngleToDir(const osg::Vec3f& dir, float dirLen = 0.0f)
{ {
float len = (dirLen > 0.0f)? dirLen : dir.length(); float len = (dirLen > 0.0f)? dirLen : dir.length();
return -Ogre::Math::ASin(dir.z / len).valueDegrees(); return osg::RadiansToDegrees(-std::asin(dir.z() / len));
} }
@ -58,20 +58,20 @@ namespace
// cast up-down ray with some offset from actor position to check for pits/obstacles on the way to target; // cast up-down ray with some offset from actor position to check for pits/obstacles on the way to target;
// magnitude of pits/obstacles is defined by PATHFIND_Z_REACH // magnitude of pits/obstacles is defined by PATHFIND_Z_REACH
bool checkWayIsClear(const Ogre::Vector3& from, const Ogre::Vector3& to, float offsetXY) bool checkWayIsClear(const osg::Vec3f& from, const osg::Vec3f& to, float offsetXY)
{ {
if((to - from).length() >= PATHFIND_CAUTION_DIST || std::abs(from.z - to.z) <= PATHFIND_Z_REACH) if((to - from).length() >= PATHFIND_CAUTION_DIST || std::abs(from.z() - to.z()) <= PATHFIND_Z_REACH)
{ {
Ogre::Vector3 dir = to - from; osg::Vec3f dir = to - from;
dir.z = 0; dir.z() = 0;
dir.normalise(); dir.normalize();
float verticalOffset = 200; // instead of '200' here we want the height of the actor float verticalOffset = 200; // instead of '200' here we want the height of the actor
Ogre::Vector3 _from = from + dir*offsetXY + Ogre::Vector3::UNIT_Z * verticalOffset; osg::Vec3f _from = from + dir*offsetXY + osg::Vec3f(0,0,1) * verticalOffset;
// cast up-down ray and find height in world space of hit // cast up-down ray and find height in world space of hit
float h = _from.z - MWBase::Environment::get().getWorld()->getDistToNearestRayHit(_from, -Ogre::Vector3::UNIT_Z, verticalOffset + PATHFIND_Z_REACH + 1); float h = _from.z() - MWBase::Environment::get().getWorld()->getDistToNearestRayHit(_from, osg::Vec3f(0,0,-1), verticalOffset + PATHFIND_Z_REACH + 1);
if(std::abs(from.z - h) <= PATHFIND_Z_REACH) if(std::abs(from.z() - h) <= PATHFIND_Z_REACH)
return true; return true;
} }
@ -95,7 +95,7 @@ namespace MWMechanics
bool mAttack; bool mAttack;
bool mFollowTarget; bool mFollowTarget;
bool mCombatMove; bool mCombatMove;
Ogre::Vector3 mLastTargetPos; osg::Vec3f mLastTargetPos;
const MWWorld::CellStore* mCell; const MWWorld::CellStore* mCell;
boost::shared_ptr<Action> mCurrentAction; boost::shared_ptr<Action> mCurrentAction;
float mActionCooldown; float mActionCooldown;
@ -104,7 +104,7 @@ namespace MWMechanics
bool mMinMaxAttackDurationInitialised; bool mMinMaxAttackDurationInitialised;
bool mForceNoShortcut; bool mForceNoShortcut;
ESM::Position mShortcutFailPos; ESM::Position mShortcutFailPos;
Ogre::Vector3 mLastActorPos; osg::Vec3f mLastActorPos;
MWMechanics::Movement mMovement; MWMechanics::Movement mMovement;
AiCombatStorage(): AiCombatStorage():
@ -231,12 +231,12 @@ namespace MWMechanics
if(movement.mRotation[2] != 0) if(movement.mRotation[2] != 0)
{ {
if(zTurn(actor, Ogre::Degree(movement.mRotation[2]))) movement.mRotation[2] = 0; if(zTurn(actor, osg::DegreesToRadians(movement.mRotation[2]))) movement.mRotation[2] = 0;
} }
if(movement.mRotation[0] != 0) if(movement.mRotation[0] != 0)
{ {
if(smoothTurn(actor, Ogre::Degree(movement.mRotation[0]), 0)) movement.mRotation[0] = 0; if(smoothTurn(actor, osg::DegreesToRadians(movement.mRotation[0]), 0)) movement.mRotation[0] = 0;
} }
float attacksPeriod = 1.0f; float attacksPeriod = 1.0f;
@ -450,12 +450,12 @@ namespace MWMechanics
*/ */
ESM::Position pos = actor.getRefData().getPosition(); ESM::Position pos = actor.getRefData().getPosition();
Ogre::Vector3 vActorPos(pos.pos); osg::Vec3f vActorPos(pos.asVec3());
Ogre::Vector3 vTargetPos(target.getRefData().getPosition().pos); osg::Vec3f vTargetPos(target.getRefData().getPosition().asVec3());
Ogre::Vector3 vDirToTarget = vTargetPos - vActorPos; osg::Vec3f vDirToTarget = vTargetPos - vActorPos;
float distToTarget = vDirToTarget.length(); float distToTarget = vDirToTarget.length();
Ogre::Vector3& lastActorPos = storage.mLastActorPos; osg::Vec3f& lastActorPos = storage.mLastActorPos;
bool& followTarget = storage.mFollowTarget; bool& followTarget = storage.mFollowTarget;
bool isStuck = false; bool isStuck = false;
@ -496,8 +496,8 @@ namespace MWMechanics
// note: in getZAngleToDir if we preserve dir.z then horizontal angle can be inaccurate // note: in getZAngleToDir if we preserve dir.z then horizontal angle can be inaccurate
if (distantCombat) if (distantCombat)
{ {
Ogre::Vector3& lastTargetPos = storage.mLastTargetPos; osg::Vec3f& lastTargetPos = storage.mLastTargetPos;
Ogre::Vector3 vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, tReaction, weaptype, strength); osg::Vec3f vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, tReaction, weaptype, strength);
lastTargetPos = vTargetPos; lastTargetPos = vTargetPos;
movement.mRotation[0] = getXAngleToDir(vAimDir); movement.mRotation[0] = getXAngleToDir(vAimDir);
movement.mRotation[2] = getZAngleToDir(vAimDir); movement.mRotation[2] = getZAngleToDir(vAimDir);
@ -553,12 +553,12 @@ namespace MWMechanics
ESM::Position& shortcutFailPos = storage.mShortcutFailPos; ESM::Position& shortcutFailPos = storage.mShortcutFailPos;
if(inLOS && (!isStuck || readyToAttack) if(inLOS && (!isStuck || readyToAttack)
&& (!forceNoShortcut || (Ogre::Vector3(shortcutFailPos.pos) - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST)) && (!forceNoShortcut || (shortcutFailPos.asVec3() - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST))
{ {
if(speed == 0.0f) speed = actorClass.getSpeed(actor); if(speed == 0.0f) speed = actorClass.getSpeed(actor);
// maximum dist before pit/obstacle for actor to avoid them depending on his speed // maximum dist before pit/obstacle for actor to avoid them depending on his speed
float maxAvoidDist = tReaction * speed + speed / MAX_VEL_ANGULAR.valueRadians() * 2; // *2 - for reliability float maxAvoidDist = tReaction * speed + speed / MAX_VEL_ANGULAR_RADIANS * 2; // *2 - for reliability
preferShortcut = checkWayIsClear(vActorPos, vTargetPos, Ogre::Vector3(vDirToTarget.x, vDirToTarget.y, 0).length() > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2); preferShortcut = checkWayIsClear(vActorPos, vTargetPos, osg::Vec3f(vDirToTarget.x(), vDirToTarget.y(), 0).length() > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2);
} }
// don't use pathgrid when actor can move in 3 dimensions // don't use pathgrid when actor can move in 3 dimensions
@ -594,7 +594,7 @@ namespace MWMechanics
// get point just before target // get point just before target
std::list<ESM::Pathgrid::Point>::const_iterator pntIter = --mPathFinder.getPath().end(); std::list<ESM::Pathgrid::Point>::const_iterator pntIter = --mPathFinder.getPath().end();
--pntIter; --pntIter;
Ogre::Vector3 vBeforeTarget(PathFinder::MakeOgreVector3(*pntIter)); osg::Vec3f vBeforeTarget(PathFinder::MakeOsgVec3(*pntIter));
// if current actor pos is closer to target then last point of path (excluding target itself) then go straight on target // if current actor pos is closer to target then last point of path (excluding target itself) then go straight on target
if(distToTarget <= (vTargetPos - vBeforeTarget).length()) if(distToTarget <= (vTargetPos - vBeforeTarget).length())
@ -668,7 +668,7 @@ namespace MWMechanics
actor.getClass().getMovementSettings(actor).mPosition[1] = 0.1f; actor.getClass().getMovementSettings(actor).mPosition[1] = 0.1f;
// change the angle a bit, too // change the angle a bit, too
if(mPathFinder.isPathConstructed()) if(mPathFinder.isPathConstructed())
zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1]))); zTurn(actor, osg::DegreesToRadians(mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1])));
if(followTarget) if(followTarget)
followTarget = false; followTarget = false;
@ -680,14 +680,14 @@ namespace MWMechanics
void AiCombat::buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target) void AiCombat::buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target)
{ {
Ogre::Vector3 newPathTarget = Ogre::Vector3(target.getRefData().getPosition().pos); osg::Vec3f newPathTarget = target.getRefData().getPosition().asVec3();
float dist; float dist;
if(!mPathFinder.getPath().empty()) if(!mPathFinder.getPath().empty())
{ {
ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back();
Ogre::Vector3 currPathTarget(PathFinder::MakeOgreVector3(lastPt)); osg::Vec3f currPathTarget(PathFinder::MakeOsgVec3(lastPt));
dist = (newPathTarget - currPathTarget).length(); dist = (newPathTarget - currPathTarget).length();
} }
else dist = 1e+38F; // necessarily construct a new path else dist = 1e+38F; // necessarily construct a new path
@ -876,7 +876,7 @@ void getMinMaxAttackDuration(const MWWorld::Ptr& actor, float (*fMinMaxDurations
} }
} }
Ogre::Vector3 AimDirToMovingTarget(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, const Ogre::Vector3& vLastTargetPos, osg::Vec3f AimDirToMovingTarget(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, const osg::Vec3f& vLastTargetPos,
float duration, int weapType, float strength) float duration, int weapType, float strength)
{ {
float projSpeed; float projSpeed;
@ -905,28 +905,37 @@ Ogre::Vector3 AimDirToMovingTarget(const MWWorld::Ptr& actor, const MWWorld::Ptr
// idea: perpendicular to dir to target speed components of target move vector and projectile vector should be the same // idea: perpendicular to dir to target speed components of target move vector and projectile vector should be the same
Ogre::Vector3 vActorPos = Ogre::Vector3(actor.getRefData().getPosition().pos); osg::Vec3f vActorPos = actor.getRefData().getPosition().asVec3();
Ogre::Vector3 vTargetPos = Ogre::Vector3(target.getRefData().getPosition().pos); osg::Vec3f vTargetPos = target.getRefData().getPosition().asVec3();
Ogre::Vector3 vDirToTarget = vTargetPos - vActorPos; osg::Vec3f vDirToTarget = vTargetPos - vActorPos;
float distToTarget = vDirToTarget.length(); float distToTarget = vDirToTarget.length();
Ogre::Vector3 vTargetMoveDir = vTargetPos - vLastTargetPos; osg::Vec3f vTargetMoveDir = vTargetPos - vLastTargetPos;
vTargetMoveDir /= duration; // |vTargetMoveDir| is target real speed in units/sec now vTargetMoveDir /= duration; // |vTargetMoveDir| is target real speed in units/sec now
Ogre::Vector3 vPerpToDir = vDirToTarget.crossProduct(Ogre::Vector3::UNIT_Z); osg::Vec3f vPerpToDir = vDirToTarget ^ osg::Vec3f(0,0,1); // cross product
float velPerp = vTargetMoveDir.dotProduct(vPerpToDir.normalisedCopy()); vPerpToDir.normalize();
float velDir = vTargetMoveDir.dotProduct(vDirToTarget.normalisedCopy()); osg::Vec3f vDirToTargetNormalized = vDirToTarget;
vDirToTargetNormalized.normalize();
// dot product
float velPerp = vTargetMoveDir * vPerpToDir;
float velDir = vTargetMoveDir * vDirToTargetNormalized;
// time to collision between target and projectile // time to collision between target and projectile
float t_collision; float t_collision;
float projVelDirSquared = projSpeed * projSpeed - velPerp * velPerp; float projVelDirSquared = projSpeed * projSpeed - velPerp * velPerp;
float projDistDiff = vDirToTarget.dotProduct(vTargetMoveDir.normalisedCopy());
projDistDiff = sqrt(distToTarget * distToTarget - projDistDiff * projDistDiff); osg::Vec3f vTargetMoveDirNormalized = vTargetMoveDir;
vTargetMoveDirNormalized.normalize();
float projDistDiff = vDirToTarget * vTargetMoveDirNormalized; // dot product
projDistDiff = std::sqrt(distToTarget * distToTarget - projDistDiff * projDistDiff);
if (projVelDirSquared > 0) if (projVelDirSquared > 0)
t_collision = projDistDiff / (sqrt(projVelDirSquared) - velDir); t_collision = projDistDiff / (std::sqrt(projVelDirSquared) - velDir);
else t_collision = 0; // speed of projectile is not enough to reach moving target else t_collision = 0; // speed of projectile is not enough to reach moving target
return vTargetPos + vTargetMoveDir * t_collision - vActorPos; return vTargetPos + vTargetMoveDir * t_collision - vActorPos;

View file

@ -76,7 +76,7 @@ bool AiFollow::execute (const MWWorld::Ptr& actor, AiState& state, float duratio
if (storage.mTimer < 0) if (storage.mTimer < 0)
{ {
if (Ogre::Vector3(actor.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(target.getRefData().getPosition().pos)) if ((actor.getRefData().getPosition().asVec3() - target.getRefData().getPosition().asVec3()).length2()
< 500*500 < 500*500
&& MWBase::Environment::get().getWorld()->getLOS(actor, target)) && MWBase::Environment::get().getWorld()->getLOS(actor, target))
mActive = true; mActive = true;
@ -137,7 +137,7 @@ bool AiFollow::execute (const MWWorld::Ptr& actor, AiState& state, float duratio
// turn towards target anyway // turn towards target anyway
float directionX = target.getRefData().getPosition().pos[0] - actor.getRefData().getPosition().pos[0]; float directionX = target.getRefData().getPosition().pos[0] - actor.getRefData().getPosition().pos[0];
float directionY = target.getRefData().getPosition().pos[1] - actor.getRefData().getPosition().pos[1]; float directionY = target.getRefData().getPosition().pos[1] - actor.getRefData().getPosition().pos[1];
zTurn(actor, Ogre::Math::ATan2(directionX,directionY), Ogre::Degree(5)); zTurn(actor, std::atan2(directionX,directionY), osg::DegreesToRadians(5.f));
} }
else else
{ {

View file

@ -106,7 +106,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po
actor.getClass().getMovementSettings(actor).mPosition[0] = 1; actor.getClass().getMovementSettings(actor).mPosition[0] = 1;
actor.getClass().getMovementSettings(actor).mPosition[1] = 1; actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
// change the angle a bit, too // change the angle a bit, too
zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1]))); zTurn(actor, osg::DegreesToRadians(mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1])));
} }
} }
else { //Not stuck, so reset things else { //Not stuck, so reset things
@ -119,7 +119,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po
actor.getClass().getMovementSettings(actor).mPosition[1] = 1; //Just run forward the rest of the time actor.getClass().getMovementSettings(actor).mPosition[1] = 1; //Just run forward the rest of the time
} }
zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); zTurn(actor, osg::DegreesToRadians(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1])));
return false; return false;
} }

View file

@ -165,7 +165,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor, AiState& state,float durati
std::list<AiPackage *>::iterator itActualCombat; std::list<AiPackage *>::iterator itActualCombat;
float nearestDist = std::numeric_limits<float>::max(); float nearestDist = std::numeric_limits<float>::max();
Ogre::Vector3 vActorPos = Ogre::Vector3(actor.getRefData().getPosition().pos); osg::Vec3f vActorPos = actor.getRefData().getPosition().asVec3();
for(std::list<AiPackage *>::iterator it = mPackages.begin(); it != mPackages.end();) for(std::list<AiPackage *>::iterator it = mPackages.begin(); it != mPackages.end();)
{ {
@ -183,7 +183,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor, AiState& state,float durati
{ {
const ESM::Position &targetPos = target.getRefData().getPosition(); const ESM::Position &targetPos = target.getRefData().getPosition();
float distTo = (Ogre::Vector3(targetPos.pos) - vActorPos).length(); float distTo = (targetPos.asVec3() - vActorPos).length();
if (distTo < nearestDist) if (distTo < nearestDist)
{ {
nearestDist = distTo; nearestDist = distTo;
@ -258,7 +258,7 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor)
return; // already in combat with this actor return; // already in combat with this actor
} }
else if ((*iter)->getTypeId() == AiPackage::TypeIdWander) else if ((*iter)->getTypeId() == AiPackage::TypeIdWander)
static_cast<AiWander*>(*iter)->setReturnPosition(Ogre::Vector3(actor.getRefData().getPosition().pos)); static_cast<AiWander*>(*iter)->setReturnPosition(actor.getRefData().getPosition().asVec3());
} }
} }

View file

@ -17,12 +17,12 @@
namespace namespace
{ {
bool isWithinMaxRange(const Ogre::Vector3& pos1, const Ogre::Vector3& pos2) bool isWithinMaxRange(const osg::Vec3f& pos1, const osg::Vec3f& pos2)
{ {
// Maximum travel distance for vanilla compatibility. // Maximum travel distance for vanilla compatibility.
// Was likely meant to prevent NPCs walking into non-loaded exterior cells, but for some reason is used in interior cells as well. // Was likely meant to prevent NPCs walking into non-loaded exterior cells, but for some reason is used in interior cells as well.
// We can make this configurable at some point, but the default *must* be the below value. Anything else will break shoddily-written content (*cough* MW *cough*) in bizarre ways. // We can make this configurable at some point, but the default *must* be the below value. Anything else will break shoddily-written content (*cough* MW *cough*) in bizarre ways.
return (pos1.squaredDistance(pos2) <= 7168*7168); return (pos1 - pos2).length2() <= 7168*7168;
} }
} }
@ -84,7 +84,7 @@ namespace MWMechanics
} }
} }
if (!isWithinMaxRange(Ogre::Vector3(mX, mY, mZ), Ogre::Vector3(pos.pos))) if (!isWithinMaxRange(osg::Vec3f(mX, mY, mZ), pos.asVec3()))
return false; return false;
bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY;
@ -106,7 +106,7 @@ namespace MWMechanics
return true; return true;
} }
zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); zTurn(actor, osg::DegreesToRadians(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1])));
movement.mPosition[1] = 1; movement.mPosition[1] = 1;
return false; return false;
@ -119,7 +119,7 @@ namespace MWMechanics
void AiTravel::fastForward(const MWWorld::Ptr& actor, AiState& state) void AiTravel::fastForward(const MWWorld::Ptr& actor, AiState& state)
{ {
if (!isWithinMaxRange(Ogre::Vector3(mX, mY, mZ), Ogre::Vector3(actor.getRefData().getPosition().pos))) if (!isWithinMaxRange(osg::Vec3f(mX, mY, mZ), actor.getRefData().getPosition().asVec3()))
return; return;
// does not do any validation on the travel target (whether it's in air, inside collision geometry, etc), // does not do any validation on the travel target (whether it's in air, inside collision geometry, etc),
// that is the user's responsibility // that is the user's responsibility

View file

@ -48,7 +48,7 @@ namespace MWMechanics
{ {
// the z rotation angle (degrees) we want to reach // the z rotation angle (degrees) we want to reach
// used every frame when mRotate is true // used every frame when mRotate is true
Ogre::Radian mTargetAngle; float mTargetAngleRadians;
bool mRotate; bool mRotate;
float mReaction; // update some actions infrequently float mReaction; // update some actions infrequently
@ -69,7 +69,7 @@ namespace MWMechanics
PathFinder mPathFinder; PathFinder mPathFinder;
AiWanderStorage(): AiWanderStorage():
mTargetAngle(0), mTargetAngleRadians(0),
mRotate(false), mRotate(false),
mReaction(0), mReaction(0),
mSaidGreeting(AiWander::Greet_None), mSaidGreeting(AiWander::Greet_None),
@ -101,7 +101,7 @@ namespace MWMechanics
mTrimCurrentNode = false; mTrimCurrentNode = false;
mHasReturnPosition = false; mHasReturnPosition = false;
mReturnPosition = Ogre::Vector3(0,0,0); mReturnPosition = osg::Vec3f(0,0,0);
if(mDistance < 0) if(mDistance < 0)
mDistance = 0; mDistance = 0;
@ -231,7 +231,7 @@ namespace MWMechanics
if(walking) // have not yet reached the destination if(walking) // have not yet reached the destination
{ {
// turn towards the next point in mPath // turn towards the next point in mPath
zTurn(actor, Ogre::Degree(storage.mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); zTurn(actor, osg::DegreesToRadians(storage.mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1])));
actor.getClass().getMovementSettings(actor).mPosition[1] = 1; actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
// Returns true if evasive action needs to be taken // Returns true if evasive action needs to be taken
@ -255,7 +255,7 @@ namespace MWMechanics
actor.getClass().getMovementSettings(actor).mPosition[0] = 1; actor.getClass().getMovementSettings(actor).mPosition[0] = 1;
actor.getClass().getMovementSettings(actor).mPosition[1] = 0.1f; actor.getClass().getMovementSettings(actor).mPosition[1] = 0.1f;
// change the angle a bit, too // change the angle a bit, too
zTurn(actor, Ogre::Degree(storage.mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1]))); zTurn(actor, osg::DegreesToRadians(storage.mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1])));
} }
mStuckCount++; // TODO: maybe no longer needed mStuckCount++; // TODO: maybe no longer needed
} }
@ -275,14 +275,14 @@ namespace MWMechanics
} }
Ogre::Radian& targetAngle = storage.mTargetAngle; float& targetAngleRadians = storage.mTargetAngleRadians;
bool& rotate = storage.mRotate; bool& rotate = storage.mRotate;
if (rotate) if (rotate)
{ {
// Reduce the turning animation glitch by using a *HUGE* value of // Reduce the turning animation glitch by using a *HUGE* value of
// epsilon... TODO: a proper fix might be in either the physics or the // epsilon... TODO: a proper fix might be in either the physics or the
// animation subsystem // animation subsystem
if (zTurn(actor, targetAngle, Ogre::Degree(5))) if (zTurn(actor, targetAngleRadians, osg::DegreesToRadians(5.f)))
rotate = false; rotate = false;
} }
@ -340,7 +340,7 @@ namespace MWMechanics
// Only say Idle voices when player is in LOS // Only say Idle voices when player is in LOS
// A bit counterintuitive, likely vanilla did this to reduce the appearance of // A bit counterintuitive, likely vanilla did this to reduce the appearance of
// voices going through walls? // voices going through walls?
if (roll < x && Ogre::Vector3(player.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(pos.pos)) if (roll < x && (player.getRefData().getPosition().asVec3() - pos.asVec3()).length2()
< 3000*3000 // maybe should be fAudioVoiceDefaultMaxDistance*fAudioMaxDistanceMult instead < 3000*3000 // maybe should be fAudioVoiceDefaultMaxDistance*fAudioMaxDistanceMult instead
&& MWBase::Environment::get().getWorld()->getLOS(player, actor)) && MWBase::Environment::get().getWorld()->getLOS(player, actor))
MWBase::Environment::get().getDialogueManager()->say(actor, "idle"); MWBase::Environment::get().getDialogueManager()->say(actor, "idle");
@ -400,7 +400,7 @@ namespace MWMechanics
// For stationary NPCs, move back to the starting location if another AiPackage moved us elsewhere // For stationary NPCs, move back to the starting location if another AiPackage moved us elsewhere
if (cellChange) if (cellChange)
mHasReturnPosition = false; mHasReturnPosition = false;
if (mDistance == 0 && mHasReturnPosition && Ogre::Vector3(pos.pos).squaredDistance(mReturnPosition) > 20*20) if (mDistance == 0 && mHasReturnPosition && (pos.asVec3() - mReturnPosition).length2() > 20*20)
{ {
chooseAction = false; chooseAction = false;
idleNow = false; idleNow = false;
@ -435,9 +435,9 @@ namespace MWMechanics
helloDistance *= iGreetDistanceMultiplier; helloDistance *= iGreetDistanceMultiplier;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
Ogre::Vector3 playerPos(player.getRefData().getPosition().pos); osg::Vec3f playerPos(player.getRefData().getPosition().asVec3());
Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos); osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3());
float playerDistSqr = playerPos.squaredDistance(actorPos); float playerDistSqr = (playerPos - actorPos).length2();
int& greetingTimer = storage.mGreetingTimer; int& greetingTimer = storage.mGreetingTimer;
if (greetingState == Greet_None) if (greetingState == Greet_None)
@ -471,10 +471,10 @@ namespace MWMechanics
if(!rotate) if(!rotate)
{ {
Ogre::Vector3 dir = playerPos - actorPos; osg::Vec3f dir = playerPos - actorPos;
float faceAngleRadians = std::atan2(dir.x, dir.y); float faceAngleRadians = std::atan2(dir.x(), dir.y());
targetAngle = faceAngleRadians; targetAngleRadians = faceAngleRadians;
rotate = true; rotate = true;
} }
@ -501,10 +501,8 @@ namespace MWMechanics
assert(mAllowedNodes.size()); assert(mAllowedNodes.size());
unsigned int randNode = Misc::Rng::rollDice(mAllowedNodes.size()); unsigned int randNode = Misc::Rng::rollDice(mAllowedNodes.size());
// NOTE: initially constructed with local (i.e. cell) co-ordinates // NOTE: initially constructed with local (i.e. cell) co-ordinates
Ogre::Vector3 destNodePos(PathFinder::MakeOgreVector3(mAllowedNodes[randNode]));
// convert dest to use world co-ordinates // convert dest to use world co-ordinates
ESM::Pathgrid::Point dest(PathFinder::MakePathgridPoint(destNodePos)); ESM::Pathgrid::Point dest(mAllowedNodes[randNode]);
if (currentCell->getCell()->isExterior()) if (currentCell->getCell()->isExterior())
{ {
dest.mX += currentCell->getCell()->mData.mX * ESM::Land::REAL_SIZE; dest.mX += currentCell->getCell()->mData.mX * ESM::Land::REAL_SIZE;
@ -607,7 +605,7 @@ namespace MWMechanics
} }
} }
void AiWander::setReturnPosition(const Ogre::Vector3& position) void AiWander::setReturnPosition(const osg::Vec3f& position)
{ {
if (!mHasReturnPosition) if (!mHasReturnPosition)
{ {
@ -652,8 +650,8 @@ namespace MWMechanics
ESM::Pathgrid::Point dest = mAllowedNodes[index]; ESM::Pathgrid::Point dest = mAllowedNodes[index];
// apply a slight offset to prevent overcrowding // apply a slight offset to prevent overcrowding
dest.mX += static_cast<int>(Ogre::Math::RangeRandom(-64, 64)); dest.mX += static_cast<int>(Misc::Rng::rollProbability() * 128 - 64);
dest.mY += static_cast<int>(Ogre::Math::RangeRandom(-64, 64)); dest.mY += static_cast<int>(Misc::Rng::rollProbability() * 128 - 64);
if (actor.getCell()->isExterior()) if (actor.getCell()->isExterior())
{ {
@ -670,7 +668,7 @@ namespace MWMechanics
{ {
if (!mStoredInitialActorPosition) if (!mStoredInitialActorPosition)
{ {
mInitialActorPosition = Ogre::Vector3(actor.getRefData().getPosition().pos); mInitialActorPosition = actor.getRefData().getPosition().asVec3();
mStoredInitialActorPosition = true; mStoredInitialActorPosition = true;
} }
@ -700,7 +698,7 @@ namespace MWMechanics
} }
// convert npcPos to local (i.e. cell) co-ordinates // convert npcPos to local (i.e. cell) co-ordinates
Ogre::Vector3 npcPos(mInitialActorPosition); osg::Vec3f npcPos(mInitialActorPosition);
npcPos[0] = npcPos[0] - cellXOffset; npcPos[0] = npcPos[0] - cellXOffset;
npcPos[1] = npcPos[1] - cellYOffset; npcPos[1] = npcPos[1] - cellYOffset;
@ -708,19 +706,19 @@ namespace MWMechanics
// NOTE: mPoints and mAllowedNodes are in local co-ordinates // NOTE: mPoints and mAllowedNodes are in local co-ordinates
for(unsigned int counter = 0; counter < pathgrid->mPoints.size(); counter++) for(unsigned int counter = 0; counter < pathgrid->mPoints.size(); counter++)
{ {
Ogre::Vector3 nodePos(PathFinder::MakeOgreVector3(pathgrid->mPoints[counter])); osg::Vec3f nodePos(PathFinder::MakeOsgVec3(pathgrid->mPoints[counter]));
if(npcPos.squaredDistance(nodePos) <= mDistance * mDistance) if((npcPos - nodePos).length2() <= mDistance * mDistance)
mAllowedNodes.push_back(pathgrid->mPoints[counter]); mAllowedNodes.push_back(pathgrid->mPoints[counter]);
} }
if(!mAllowedNodes.empty()) if(!mAllowedNodes.empty())
{ {
Ogre::Vector3 firstNodePos(PathFinder::MakeOgreVector3(mAllowedNodes[0])); osg::Vec3f firstNodePos(PathFinder::MakeOsgVec3(mAllowedNodes[0]));
float closestNode = npcPos.squaredDistance(firstNodePos); float closestNode = (npcPos - firstNodePos).length2();
unsigned int index = 0; unsigned int index = 0;
for(unsigned int counterThree = 1; counterThree < mAllowedNodes.size(); counterThree++) for(unsigned int counterThree = 1; counterThree < mAllowedNodes.size(); counterThree++)
{ {
Ogre::Vector3 nodePos(PathFinder::MakeOgreVector3(mAllowedNodes[counterThree])); osg::Vec3f nodePos(PathFinder::MakeOsgVec3(mAllowedNodes[counterThree]));
float tempDist = npcPos.squaredDistance(nodePos); float tempDist = (npcPos - nodePos).length2();
if(tempDist < closestNode) if(tempDist < closestNode)
index = counterThree; index = counterThree;
} }
@ -737,7 +735,7 @@ namespace MWMechanics
std::vector<PathDistance> nodeDistances; std::vector<PathDistance> nodeDistances;
for (unsigned int counter = 0; counter < pathgrid->mPoints.size(); counter++) for (unsigned int counter = 0; counter < pathgrid->mPoints.size(); counter++)
{ {
float distance = npcPos.squaredDistance(PathFinder::MakeOgreVector3(pathgrid->mPoints[counter])); float distance = (npcPos - PathFinder::MakeOsgVec3(pathgrid->mPoints[counter])).length2();
nodeDistances.push_back(std::make_pair(distance, &pathgrid->mPoints.at(counter))); nodeDistances.push_back(std::make_pair(distance, &pathgrid->mPoints.at(counter)));
} }
std::sort(nodeDistances.begin(), nodeDistances.end(), sortByDistance); std::sort(nodeDistances.begin(), nodeDistances.end(), sortByDistance);

View file

@ -54,7 +54,7 @@ namespace MWMechanics
/// Set the position to return to for a stationary (non-wandering) actor /// Set the position to return to for a stationary (non-wandering) actor
/** In case another AI package moved the actor elsewhere **/ /** In case another AI package moved the actor elsewhere **/
void setReturnPosition (const Ogre::Vector3& position); void setReturnPosition (const osg::Vec3f& position);
virtual void writeState(ESM::AiSequence::AiSequence &sequence) const; virtual void writeState(ESM::AiSequence::AiSequence &sequence) const;
@ -83,9 +83,9 @@ namespace MWMechanics
bool mHasReturnPosition; // NOTE: Could be removed if mReturnPosition was initialized to actor position, bool mHasReturnPosition; // NOTE: Could be removed if mReturnPosition was initialized to actor position,
// if we had the actor in the AiWander constructor... // if we had the actor in the AiWander constructor...
Ogre::Vector3 mReturnPosition; osg::Vec3f mReturnPosition;
Ogre::Vector3 mInitialActorPosition; osg::Vec3f mInitialActorPosition;
bool mStoredInitialActorPosition; bool mStoredInitialActorPosition;

View file

@ -1531,7 +1531,7 @@ void CharacterController::update(float duration)
if(mHitState != CharState_None && mJumpState == JumpState_None) if(mHitState != CharState_None && mJumpState == JumpState_None)
vec = osg::Vec3f(0.f, 0.f, 0.f); vec = osg::Vec3f(0.f, 0.f, 0.f);
Ogre::Vector3 rot = cls.getRotationVector(mPtr); osg::Vec3f rot = cls.getRotationVector(mPtr);
mMovementSpeed = cls.getSpeed(mPtr); mMovementSpeed = cls.getSpeed(mPtr);
@ -1728,11 +1728,11 @@ void CharacterController::update(float duration)
// Don't play turning animations during attack. It would break positioning of the arrow bone when releasing a shot. // Don't play turning animations during attack. It would break positioning of the arrow bone when releasing a shot.
// Actually, in vanilla the turning animation is not even played when merely having equipped the weapon, // Actually, in vanilla the turning animation is not even played when merely having equipped the weapon,
// but I don't think we need to go as far as that. // but I don't think we need to go as far as that.
else if(rot.z != 0.0f && !inwater && !sneak && mUpperBodyState < UpperCharState_StartToMinAttack) else if(rot.z() != 0.0f && !inwater && !sneak && mUpperBodyState < UpperCharState_StartToMinAttack)
{ {
if(rot.z > 0.0f) if(rot.z() > 0.0f)
movestate = CharState_TurnRight; movestate = CharState_TurnRight;
else if(rot.z < 0.0f) else if(rot.z() < 0.0f)
movestate = CharState_TurnLeft; movestate = CharState_TurnLeft;
} }
} }
@ -1782,18 +1782,18 @@ void CharacterController::update(float duration)
if (mMovementState == CharState_TurnLeft || mMovementState == CharState_TurnRight) if (mMovementState == CharState_TurnLeft || mMovementState == CharState_TurnRight)
{ {
if (duration > 0) if (duration > 0)
mAnimation->adjustSpeedMult(mCurrentMovement, std::min(1.5f, std::abs(rot.z) / duration / Ogre::Math::PI)); mAnimation->adjustSpeedMult(mCurrentMovement, std::min(1.5f, std::abs(rot.z()) / duration / Ogre::Math::PI));
} }
if (!mSkipAnim) if (!mSkipAnim)
{ {
rot *= Ogre::Math::RadiansToDegrees(1.0f); rot *= osg::RadiansToDegrees(1.0f);
if(mHitState != CharState_KnockDown && mHitState != CharState_KnockOut) if(mHitState != CharState_KnockDown && mHitState != CharState_KnockOut)
{ {
world->rotateObject(mPtr, rot.x, rot.y, rot.z, true); world->rotateObject(mPtr, rot.x(), rot.y(), rot.z(), true);
} }
else //avoid z-rotating for knockdown else //avoid z-rotating for knockdown
world->rotateObject(mPtr, rot.x, rot.y, 0.0f, true); world->rotateObject(mPtr, rot.x(), rot.y(), 0.0f, true);
if (!mMovementAnimationControlled) if (!mMovementAnimationControlled)
world->queueMovement(mPtr, vec); world->queueMovement(mPtr, vec);

View file

@ -15,9 +15,9 @@ namespace
// Caller needs to be careful for very short distances (i.e. less than 1) // Caller needs to be careful for very short distances (i.e. less than 1)
// or when accumuating the results i.e. (a + b)^2 != a^2 + b^2 // or when accumuating the results i.e. (a + b)^2 != a^2 + b^2
// //
float distanceSquared(ESM::Pathgrid::Point point, Ogre::Vector3 pos) float distanceSquared(ESM::Pathgrid::Point point, const osg::Vec3f& pos)
{ {
return MWMechanics::PathFinder::MakeOgreVector3(point).squaredDistance(pos); return (MWMechanics::PathFinder::MakeOsgVec3(point) - pos).length2();
} }
// Return the closest pathgrid point index from the specified position co // Return the closest pathgrid point index from the specified position co
@ -26,7 +26,7 @@ namespace
// //
// NOTE: pos is expected to be in local co-ordinates, as is grid->mPoints // NOTE: pos is expected to be in local co-ordinates, as is grid->mPoints
// //
int getClosestPoint(const ESM::Pathgrid* grid, Ogre::Vector3 pos) int getClosestPoint(const ESM::Pathgrid* grid, const osg::Vec3f& pos)
{ {
if(!grid || grid->mPoints.empty()) if(!grid || grid->mPoints.empty())
return -1; return -1;
@ -52,7 +52,7 @@ namespace
// Chooses a reachable end pathgrid point. start is assumed reachable. // Chooses a reachable end pathgrid point. start is assumed reachable.
std::pair<int, bool> getClosestReachablePoint(const ESM::Pathgrid* grid, std::pair<int, bool> getClosestReachablePoint(const ESM::Pathgrid* grid,
const MWWorld::CellStore *cell, const MWWorld::CellStore *cell,
Ogre::Vector3 pos, int start) const osg::Vec3f pos, int start)
{ {
if(!grid || grid->mPoints.empty()) if(!grid || grid->mPoints.empty())
return std::pair<int, bool> (-1, false); return std::pair<int, bool> (-1, false);
@ -216,12 +216,12 @@ namespace MWMechanics
// point right behind the wall that is closer than any pathgrid // point right behind the wall that is closer than any pathgrid
// point outside the wall // point outside the wall
int startNode = getClosestPoint(mPathgrid, int startNode = getClosestPoint(mPathgrid,
Ogre::Vector3(startPoint.mX - xCell, startPoint.mY - yCell, static_cast<float>(startPoint.mZ))); osg::Vec3f(startPoint.mX - xCell, startPoint.mY - yCell, static_cast<float>(startPoint.mZ)));
// Some cells don't have any pathgrids at all // Some cells don't have any pathgrids at all
if(startNode != -1) if(startNode != -1)
{ {
std::pair<int, bool> endNode = getClosestReachablePoint(mPathgrid, cell, std::pair<int, bool> endNode = getClosestReachablePoint(mPathgrid, cell,
Ogre::Vector3(endPoint.mX - xCell, endPoint.mY - yCell, static_cast<float>(endPoint.mZ)), osg::Vec3f(endPoint.mX - xCell, endPoint.mY - yCell, static_cast<float>(endPoint.mZ)),
startNode); startNode);
// this shouldn't really happen, but just in case // this shouldn't really happen, but just in case
@ -279,7 +279,7 @@ namespace MWMechanics
float directionX = nextPoint.mX - x; float directionX = nextPoint.mX - x;
float directionY = nextPoint.mY - y; float directionY = nextPoint.mY - y;
return Ogre::Math::ATan2(directionX,directionY).valueDegrees(); return osg::RadiansToDegrees(std::atan2(directionX, directionY));
} }
bool PathFinder::checkPathCompleted(float x, float y, float tolerance) bool PathFinder::checkPathCompleted(float x, float y, float tolerance)

View file

@ -44,6 +44,7 @@ namespace MWMechanics
bool checkPathCompleted(float x, float y, float tolerance=32.f); bool checkPathCompleted(float x, float y, float tolerance=32.f);
///< \Returns true if we are within \a tolerance units of the last path point. ///< \Returns true if we are within \a tolerance units of the last path point.
/// In degrees
float getZAngleToNext(float x, float y) const; float getZAngleToNext(float x, float y) const;
bool isPathConstructed() const bool isPathConstructed() const
@ -82,6 +83,12 @@ namespace MWMechanics
return ESM::Pathgrid::Point(static_cast<int>(v[0]), static_cast<int>(v[1]), static_cast<int>(v[2])); return ESM::Pathgrid::Point(static_cast<int>(v[0]), static_cast<int>(v[1]), static_cast<int>(v[2]));
} }
/// utility function to convert a osg::Vec3f to a Pathgrid::Point
static ESM::Pathgrid::Point MakePathgridPoint(const osg::Vec3f& v)
{
return ESM::Pathgrid::Point(static_cast<int>(v[0]), static_cast<int>(v[1]), static_cast<int>(v[2]));
}
/// utility function to convert an ESM::Position to a Pathgrid::Point /// utility function to convert an ESM::Position to a Pathgrid::Point
static ESM::Pathgrid::Point MakePathgridPoint(const ESM::Position& p) static ESM::Pathgrid::Point MakePathgridPoint(const ESM::Position& p)
{ {

View file

@ -10,37 +10,37 @@
namespace MWMechanics namespace MWMechanics
{ {
bool smoothTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle, int axis, Ogre::Degree epsilon) bool smoothTurn(const MWWorld::Ptr& actor, float targetAngleRadians, int axis, float epsilonRadians)
{ {
Ogre::Radian currentAngle (actor.getRefData().getPosition().rot[axis]); float currentAngle (actor.getRefData().getPosition().rot[axis]);
Ogre::Radian diff (targetAngle - currentAngle); float diff (targetAngleRadians - currentAngle);
if (diff >= Ogre::Degree(180)) if (diff >= osg::DegreesToRadians(180.f))
{ {
// Turning the other way would be a better idea // Turning the other way would be a better idea
diff = diff-Ogre::Degree(360); diff = diff-osg::DegreesToRadians(360.f);
} }
else if (diff <= Ogre::Degree(-180)) else if (diff <= osg::DegreesToRadians(-180.f))
{ {
diff = Ogre::Degree(360)-diff; diff = osg::DegreesToRadians(360.f)-diff;
} }
Ogre::Radian absDiff = Ogre::Math::Abs(diff); float absDiff = std::abs(diff);
// The turning animation actually moves you slightly, so the angle will be wrong again. // The turning animation actually moves you slightly, so the angle will be wrong again.
// Use epsilon to prevent jerkiness. // Use epsilon to prevent jerkiness.
if (absDiff < epsilon) if (absDiff < epsilonRadians)
return true; return true;
Ogre::Radian limit = MAX_VEL_ANGULAR * MWBase::Environment::get().getFrameDuration(); float limit = MAX_VEL_ANGULAR_RADIANS * MWBase::Environment::get().getFrameDuration();
if (absDiff > limit) if (absDiff > limit)
diff = Ogre::Math::Sign(diff) * limit; diff = osg::sign(diff) * limit;
actor.getClass().getMovementSettings(actor).mRotation[axis] = diff.valueRadians(); actor.getClass().getMovementSettings(actor).mRotation[axis] = diff;
return false; return false;
} }
bool zTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle, Ogre::Degree epsilon) bool zTurn(const MWWorld::Ptr& actor, float targetAngleRadians, float epsilonRadians)
{ {
return smoothTurn(actor, targetAngle, 2, epsilon); return smoothTurn(actor, targetAngleRadians, 2, epsilonRadians);
} }
} }

View file

@ -1,6 +1,6 @@
#ifndef OPENMW_MECHANICS_STEERING_H #ifndef OPENMW_MECHANICS_STEERING_H
#include <OgreMath.h> #include <osg/Math>
namespace MWWorld namespace MWWorld
{ {
@ -11,15 +11,15 @@ namespace MWMechanics
{ {
// Max rotating speed, radian/sec // Max rotating speed, radian/sec
const Ogre::Radian MAX_VEL_ANGULAR(10); const float MAX_VEL_ANGULAR_RADIANS(10);
/// configure rotation settings for an actor to reach this target angle (eventually) /// configure rotation settings for an actor to reach this target angle (eventually)
/// @return have we reached the target angle? /// @return have we reached the target angle?
bool zTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle, bool zTurn(const MWWorld::Ptr& actor, float targetAngleRadians,
Ogre::Degree epsilon = Ogre::Degree(0.5)); float epsilonRadians = osg::DegreesToRadians(0.5));
bool smoothTurn(const MWWorld::Ptr& actor, Ogre::Radian targetAngle, int axis, bool smoothTurn(const MWWorld::Ptr& actor, float targetAngleRadians, int axis,
Ogre::Degree epsilon = Ogre::Degree(0.5)); float epsilonRadians = osg::DegreesToRadians(0.5));
} }

View file

@ -186,9 +186,9 @@ namespace MWWorld
throw std::runtime_error ("movement settings not supported by class"); throw std::runtime_error ("movement settings not supported by class");
} }
Ogre::Vector3 Class::getRotationVector (const Ptr& ptr) const osg::Vec3f Class::getRotationVector (const Ptr& ptr) const
{ {
return Ogre::Vector3 (0, 0, 0); return osg::Vec3f (0, 0, 0);
} }
std::pair<std::vector<int>, bool> Class::getEquipmentSlots (const Ptr& ptr) const std::pair<std::vector<int>, bool> Class::getEquipmentSlots (const Ptr& ptr) const

View file

@ -192,7 +192,7 @@ namespace MWWorld
virtual MWMechanics::Movement& getMovementSettings (const Ptr& ptr) const; virtual MWMechanics::Movement& getMovementSettings (const Ptr& ptr) const;
///< Return desired movement. ///< Return desired movement.
virtual Ogre::Vector3 getRotationVector (const Ptr& ptr) const; virtual osg::Vec3f getRotationVector (const Ptr& ptr) const;
///< Return desired rotations, as euler angles. ///< Return desired rotations, as euler angles.
virtual std::pair<std::vector<int>, bool> getEquipmentSlots (const Ptr& ptr) const; virtual std::pair<std::vector<int>, bool> getEquipmentSlots (const Ptr& ptr) const;

View file

@ -206,9 +206,9 @@ namespace MWWorld
player.mBirthsign = mSign; player.mBirthsign = mSign;
player.mLastKnownExteriorPosition[0] = mLastKnownExteriorPosition.x; player.mLastKnownExteriorPosition[0] = mLastKnownExteriorPosition.x();
player.mLastKnownExteriorPosition[1] = mLastKnownExteriorPosition.y; player.mLastKnownExteriorPosition[1] = mLastKnownExteriorPosition.y();
player.mLastKnownExteriorPosition[2] = mLastKnownExteriorPosition.z; player.mLastKnownExteriorPosition[2] = mLastKnownExteriorPosition.z();
if (mMarkedCell) if (mMarkedCell)
{ {
@ -279,9 +279,9 @@ namespace MWWorld
mSign = player.mBirthsign; mSign = player.mBirthsign;
mLastKnownExteriorPosition.x = player.mLastKnownExteriorPosition[0]; mLastKnownExteriorPosition.x() = player.mLastKnownExteriorPosition[0];
mLastKnownExteriorPosition.y = player.mLastKnownExteriorPosition[1]; mLastKnownExteriorPosition.y() = player.mLastKnownExteriorPosition[1];
mLastKnownExteriorPosition.z = player.mLastKnownExteriorPosition[2]; mLastKnownExteriorPosition.z() = player.mLastKnownExteriorPosition[2];
if (player.mHasMark && !player.mMarkedCell.mPaged) if (player.mHasMark && !player.mMarkedCell.mPaged)
{ {

View file

@ -37,7 +37,7 @@ namespace MWWorld
MWWorld::CellStore *mCellStore; MWWorld::CellStore *mCellStore;
std::string mSign; std::string mSign;
Ogre::Vector3 mLastKnownExteriorPosition; osg::Vec3f mLastKnownExteriorPosition;
ESM::Position mMarkedPosition; ESM::Position mMarkedPosition;
// If no position was marked, this is NULL // If no position was marked, this is NULL
@ -61,9 +61,8 @@ namespace MWWorld
/// Interiors can not always be mapped to a world position. However /// Interiors can not always be mapped to a world position. However
/// world position is still required for divine / almsivi magic effects /// world position is still required for divine / almsivi magic effects
/// and the player arrow on the global map. /// and the player arrow on the global map.
/// TODO: This should be stored in the savegame, too. void setLastKnownExteriorPosition (const osg::Vec3f& position) { mLastKnownExteriorPosition = position; }
void setLastKnownExteriorPosition (const Ogre::Vector3& position) { mLastKnownExteriorPosition = position; } osg::Vec3f getLastKnownExteriorPosition() const { return mLastKnownExteriorPosition; }
Ogre::Vector3 getLastKnownExteriorPosition() const { return mLastKnownExteriorPosition; }
void set (const ESM::NPC *player); void set (const ESM::NPC *player);

View file

@ -1585,7 +1585,7 @@ namespace MWWorld
if (player.getCell()->isExterior()) if (player.getCell()->isExterior())
{ {
ESM::Position pos = player.getRefData().getPosition(); ESM::Position pos = player.getRefData().getPosition();
mPlayer->setLastKnownExteriorPosition(Ogre::Vector3(pos.pos)); mPlayer->setLastKnownExteriorPosition(pos.asVec3());
} }
if (player.getClass().getNpcStats(player).isWerewolf()) if (player.getClass().getNpcStats(player).isWerewolf())
@ -2324,20 +2324,19 @@ namespace MWWorld
return mPhysics->getLineOfSight(actor, targetActor); return mPhysics->getLineOfSight(actor, targetActor);
} }
float World::getDistToNearestRayHit(const Ogre::Vector3& from, const Ogre::Vector3& dir, float maxDist) float World::getDistToNearestRayHit(const osg::Vec3f& from, const osg::Vec3f& dir, float maxDist)
{ {
osg::Vec3f from_ (from.x, from.y, from.z); osg::Vec3f to (dir);
osg::Vec3f to_ (dir.x, dir.y, dir.z); to.normalize();
to_.normalize(); to = from + (to * maxDist);
to_ = from_ + (to_ * maxDist);
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(from_, to_, MWWorld::Ptr(), MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(from, to, MWWorld::Ptr(),
MWPhysics::CollisionType_World|MWPhysics::CollisionType_HeightMap); MWPhysics::CollisionType_World|MWPhysics::CollisionType_HeightMap);
if (!result.mHit) if (!result.mHit)
return maxDist; return maxDist;
else else
return (result.mHitPos - from_).length(); return (result.mHitPos - from).length();
} }
void World::enableActorCollision(const MWWorld::Ptr& actor, bool enable) void World::enableActorCollision(const MWWorld::Ptr& actor, bool enable)
@ -2731,7 +2730,7 @@ namespace MWWorld
} }
} }
bool World::findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, Ogre::Vector3& result) bool World::findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, osg::Vec3f& result)
{ {
if (cell->isExterior()) if (cell->isExterior())
return false; return false;
@ -2762,7 +2761,7 @@ namespace MWWorld
if (ref.mRef.getDestCell().empty()) if (ref.mRef.getDestCell().empty())
{ {
ESM::Position pos = ref.mRef.getDoorDest(); ESM::Position pos = ref.mRef.getDoorDest();
result = Ogre::Vector3(pos.pos); result = pos.asVec3();
return true; return true;
} }
else else
@ -2822,7 +2821,7 @@ namespace MWWorld
if (ref.mRef.getDestCell().empty()) if (ref.mRef.getDestCell().empty())
{ {
Ogre::Vector3 worldPos = Ogre::Vector3(ref.mRef.getDoorDest().pos); osg::Vec3f worldPos = ref.mRef.getDoorDest().asVec3();
return getClosestMarkerFromExteriorPosition(worldPos, id); return getClosestMarkerFromExteriorPosition(worldPos, id);
} }
else else
@ -2838,7 +2837,7 @@ namespace MWWorld
return MWWorld::Ptr(); return MWWorld::Ptr();
} }
MWWorld::Ptr World::getClosestMarkerFromExteriorPosition( const Ogre::Vector3 worldPos, const std::string &id ) { MWWorld::Ptr World::getClosestMarkerFromExteriorPosition( const osg::Vec3f& worldPos, const std::string &id ) {
MWWorld::Ptr closestMarker; MWWorld::Ptr closestMarker;
float closestDistance = FLT_MAX; float closestDistance = FLT_MAX;
@ -2847,8 +2846,8 @@ namespace MWWorld
for (std::vector<MWWorld::Ptr>::iterator it2 = markers.begin(); it2 != markers.end(); ++it2) for (std::vector<MWWorld::Ptr>::iterator it2 = markers.begin(); it2 != markers.end(); ++it2)
{ {
ESM::Position pos = it2->getRefData().getPosition(); ESM::Position pos = it2->getRefData().getPosition();
Ogre::Vector3 markerPos = Ogre::Vector3(pos.pos); osg::Vec3f markerPos = pos.asVec3();
float distance = worldPos.squaredDistance(markerPos); float distance = (worldPos - markerPos).length2();
if (distance < closestDistance) if (distance < closestDistance)
{ {
closestDistance = distance; closestDistance = distance;

View file

@ -156,7 +156,7 @@ namespace MWWorld
float feetToGameUnits(float feet); float feetToGameUnits(float feet);
MWWorld::Ptr getClosestMarker( const MWWorld::Ptr &ptr, const std::string &id ); MWWorld::Ptr getClosestMarker( const MWWorld::Ptr &ptr, const std::string &id );
MWWorld::Ptr getClosestMarkerFromExteriorPosition( const Ogre::Vector3 worldPos, const std::string &id ); MWWorld::Ptr getClosestMarkerFromExteriorPosition( const osg::Vec3f& worldPos, const std::string &id );
public: public:
@ -508,7 +508,7 @@ namespace MWWorld
virtual bool getLOS(const MWWorld::Ptr& actor,const MWWorld::Ptr& targetActor); virtual bool getLOS(const MWWorld::Ptr& actor,const MWWorld::Ptr& targetActor);
///< get Line of Sight (morrowind stupid implementation) ///< get Line of Sight (morrowind stupid implementation)
virtual float getDistToNearestRayHit(const Ogre::Vector3& from, const Ogre::Vector3& dir, float maxDist); virtual float getDistToNearestRayHit(const osg::Vec3f& from, const osg::Vec3f& dir, float maxDist);
virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable); virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable);
@ -583,7 +583,7 @@ namespace MWWorld
// Are we in an exterior or pseudo-exterior cell and it's night? // Are we in an exterior or pseudo-exterior cell and it's night?
virtual bool isDark() const; virtual bool isDark() const;
virtual bool findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, Ogre::Vector3& result); virtual bool findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, osg::Vec3f& result);
/// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker) /// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)
/// @note id must be lower case /// @note id must be lower case