Restore getHitContact

c++11
scrawl 10 years ago
parent 627fee07bc
commit 85345e663a

@ -262,7 +262,7 @@ namespace MWBase
/// Returns a pointer to the object the provided object would hit (if within the
/// specified distance), and the point where the hit occurs. This will attempt to
/// use the "Head" node, or alternatively the "Bip01 Head" node as a basis.
virtual std::pair<MWWorld::Ptr,Ogre::Vector3> getHitContact(const MWWorld::Ptr &ptr, float distance) = 0;
virtual std::pair<MWWorld::Ptr,osg::Vec3f> getHitContact(const MWWorld::Ptr &ptr, float distance) = 0;
virtual void adjustPosition (const MWWorld::Ptr& ptr, bool force) = 0;
///< Adjust position after load to be on ground. Must be called after model load.

@ -238,7 +238,7 @@ namespace MWClass
const float fCombatDistance = gmst.find("fCombatDistance")->getFloat();
dist = fCombatDistance * weapon.get<ESM::Weapon>()->mBase->mData.mReach;
}
std::pair<MWWorld::Ptr, Ogre::Vector3> result = MWBase::Environment::get().getWorld()->getHitContact(ptr, dist);
std::pair<MWWorld::Ptr, osg::Vec3f> result = MWBase::Environment::get().getWorld()->getHitContact(ptr, dist);
if (result.first.isEmpty())
return; // Didn't hit anything
@ -247,7 +247,7 @@ namespace MWClass
if (!victim.getClass().isActor())
return; // Can't hit non-actors
Ogre::Vector3 hitPosition = result.second;
Ogre::Vector3 hitPosition (result.second.x(), result.second.y(), result.second.z());
float hitchance = MWMechanics::getHitChance(ptr, victim, ref->mBase->mData.mCombat);

@ -491,9 +491,9 @@ namespace MWClass
store.find("fHandToHandReach")->getFloat());
// TODO: Use second to work out the hit angle
std::pair<MWWorld::Ptr, Ogre::Vector3> result = world->getHitContact(ptr, dist);
std::pair<MWWorld::Ptr, osg::Vec3f> result = world->getHitContact(ptr, dist);
MWWorld::Ptr victim = result.first;
Ogre::Vector3 hitPosition = result.second;
Ogre::Vector3 hitPosition (result.second.x(), result.second.y(), result.second.z());
if(victim.isEmpty()) // Didn't hit anything
return;

@ -31,6 +31,11 @@ namespace MWPhysics
mPtr = updated;
}
MWWorld::Ptr getPtr() const
{
return mPtr;
}
protected:
MWWorld::Ptr mPtr;
};

@ -653,35 +653,78 @@ namespace MWPhysics
return mDebugDrawEnabled;
}
std::pair<std::string,Ogre::Vector3> PhysicsSystem::getHitContact(const std::string &name,
const Ogre::Vector3 &origin,
const Ogre::Quaternion &orient,
class DeepestNotMeContactTestResultCallback : public btCollisionWorld::ContactResultCallback
{
const btCollisionObject* mMe;
// Store the real origin, since the shape's origin is its center
btVector3 mOrigin;
public:
const btCollisionObject *mObject;
btVector3 mContactPoint;
btScalar mLeastDistSqr;
DeepestNotMeContactTestResultCallback(const btCollisionObject* me, const btVector3 &origin)
: mMe(me), mOrigin(origin), mObject(NULL), mContactPoint(0,0,0),
mLeastDistSqr(std::numeric_limits<float>::max())
{ }
virtual btScalar addSingleResult(btManifoldPoint& cp,
const btCollisionObjectWrapper* col0Wrap,int partId0,int index0,
const btCollisionObjectWrapper* col1Wrap,int partId1,int index1)
{
if (col1Wrap->m_collisionObject != mMe)
{
btScalar distsqr = mOrigin.distance2(cp.getPositionWorldOnA());
if(!mObject || distsqr < mLeastDistSqr)
{
mObject = col1Wrap->m_collisionObject;
mLeastDistSqr = distsqr;
mContactPoint = cp.getPositionWorldOnA();
}
}
return 0.f;
}
};
std::pair<MWWorld::Ptr, osg::Vec3f> PhysicsSystem::getHitContact(const MWWorld::Ptr& actor,
const osg::Vec3f &origin,
const osg::Quat &orient,
float queryDistance)
{
return std::make_pair(std::string(), Ogre::Vector3());
/*
const MWWorld::Store<ESM::GameSetting> &store = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
btConeShape shape(Ogre::Degree(store.find("fCombatAngleXY")->getFloat()/2.0f).valueRadians(),
queryDistance);
shape.setLocalScaling(btVector3(1, 1, Ogre::Degree(store.find("fCombatAngleZ")->getFloat()/2.0f).valueRadians() /
btConeShape shape (osg::DegreesToRadians(store.find("fCombatAngleXY")->getFloat()/2.0f), queryDistance);
shape.setLocalScaling(btVector3(1, 1, osg::DegreesToRadians(store.find("fCombatAngleZ")->getFloat()/2.0f) /
shape.getRadius()));
// The shape origin is its center, so we have to move it forward by half the length. The
// real origin will be provided to getFilteredContact to find the closest.
Ogre::Vector3 center = origin + (orient * Ogre::Vector3(0.0f, queryDistance*0.5f, 0.0f));
osg::Vec3f center = origin + (orient * osg::Vec3f(0.0f, queryDistance*0.5f, 0.0f));
btCollisionObject object;
object.setCollisionShape(&shape);
object.setWorldTransform(btTransform(btQuaternion(orient.x, orient.y, orient.z, orient.w),
btVector3(center.x, center.y, center.z)));
std::pair<const OEngine::Physic::RigidBody*,btVector3> result = mEngine->getFilteredContact(
name, btVector3(origin.x, origin.y, origin.z), &object);
if(!result.first)
return std::make_pair(std::string(), Ogre::Vector3(&result.second[0]));
return std::make_pair(result.first->mName, Ogre::Vector3(&result.second[0]));
*/
object.setWorldTransform(btTransform(toBullet(orient), toBullet(center)));
const btCollisionObject* me = NULL;
Actor* physactor = getActor(actor);
if (physactor)
me = physactor->getCollisionObject();
DeepestNotMeContactTestResultCallback resultCallback(me, toBullet(origin));
resultCallback.m_collisionFilterGroup = CollisionType_Actor;
resultCallback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap | CollisionType_Actor;
mDynamicsWorld->contactTest(&object, resultCallback);
if (resultCallback.mObject)
{
const PtrHolder* holder = static_cast<const PtrHolder*>(resultCallback.mObject->getUserPointer());
if (holder)
return std::make_pair(holder->getPtr(), toOsg(resultCallback.mContactPoint));
}
return std::make_pair(MWWorld::Ptr(), osg::Vec3f());
}

@ -11,6 +11,8 @@
#include "../mwworld/ptr.hpp"
#include <osg/Quat>
namespace osg
{
class Group;
@ -78,9 +80,9 @@ namespace MWPhysics
std::vector<std::string> getCollisions(const MWWorld::Ptr &ptr, int collisionGroup, int collisionMask); ///< get handles this object collides with
osg::Vec3f traceDown(const MWWorld::Ptr &ptr, float maxHeight);
std::pair<std::string,Ogre::Vector3> getHitContact(const std::string &name,
const Ogre::Vector3 &origin,
const Ogre::Quaternion &orientation,
std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::Ptr& actor,
const osg::Vec3f &origin,
const osg::Quat &orientation,
float queryDistance);
// cast ray, return true if it hit something.

@ -315,6 +315,9 @@ namespace MWRender
MWRender::Animation* RenderingManager::getAnimation(const MWWorld::Ptr &ptr)
{
if (mPlayerAnimation.get() && ptr == mPlayerAnimation->getPtr())
return mPlayerAnimation.get();
return mObjects->getAnimation(ptr);
}

@ -37,7 +37,7 @@
#include "../mwmechanics/combat.hpp"
#include "../mwmechanics/aiavoiddoor.hpp" //Used to tell actors to avoid doors
//#include "../mwrender/animation.hpp"
#include "../mwrender/animation.hpp"
#include "../mwrender/renderingmanager.hpp"
#include "../mwrender/camera.hpp"
@ -1052,32 +1052,32 @@ namespace MWWorld
//return getPtrViaHandle(facedHandle);
}
std::pair<MWWorld::Ptr,Ogre::Vector3> World::getHitContact(const MWWorld::Ptr &ptr, float distance)
std::pair<MWWorld::Ptr,osg::Vec3f> World::getHitContact(const MWWorld::Ptr &ptr, float distance)
{
/*
const ESM::Position &posdata = ptr.getRefData().getPosition();
Ogre::Vector3 pos(posdata.pos);
Ogre::Quaternion rot = Ogre::Quaternion(Ogre::Radian(posdata.rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) *
Ogre::Quaternion(Ogre::Radian(posdata.rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X);
MWRender::Animation *anim = mRendering->getAnimation(ptr);
if(anim != NULL)
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());
MWRender::Animation* anim = mRendering->getAnimation(ptr);
if (anim != NULL)
{
Ogre::Node *node = anim->getNode("Head");
const osg::Node* node = anim->getNode("Head");
if (node == NULL)
node = anim->getNode("Bip01 Head");
if(node != NULL)
pos += node->_getDerivedPosition();
if (node != NULL)
{
osg::MatrixList mats = node->getWorldMatrices();
if (mats.size())
pos = mats[0].getTrans();
}
}
std::pair<std::string,Ogre::Vector3> result;// = mPhysics->getHitContact(ptr.getRefData().getHandle(),
// pos, rot, distance);
if(result.first.empty())
return std::make_pair(MWWorld::Ptr(), Ogre::Vector3(0.0f));
std::pair<MWWorld::Ptr,osg::Vec3f> result = mPhysics->getHitContact(ptr, pos, rot, distance);
if(result.first.isEmpty())
return std::make_pair(MWWorld::Ptr(), osg::Vec3f());
return std::make_pair(searchPtrViaHandle(result.first), result.second);
*/
return std::make_pair(MWWorld::Ptr(), Ogre::Vector3(0.0f));
return std::make_pair(result.first, result.second);
}
void World::deleteObject (const Ptr& ptr)

@ -344,7 +344,7 @@ namespace MWWorld
/// Returns a pointer to the object the provided object would hit (if within the
/// specified distance), and the point where the hit occurs. This will attempt to
/// use the "Head" node as a basis.
virtual std::pair<MWWorld::Ptr,Ogre::Vector3> getHitContact(const MWWorld::Ptr &ptr, float distance);
virtual std::pair<MWWorld::Ptr,osg::Vec3f> getHitContact(const MWWorld::Ptr &ptr, float distance);
virtual void deleteObject (const Ptr& ptr);
virtual void undeleteObject (const Ptr& ptr);

Loading…
Cancel
Save