1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-04 07:13:29 +00:00

Restore getHitContact

This commit is contained in:
scrawl 2015-05-22 04:36:17 +02:00
parent 627fee07bc
commit 85345e663a
9 changed files with 97 additions and 44 deletions

View File

@ -262,7 +262,7 @@ namespace MWBase
/// Returns a pointer to the object the provided object would hit (if within the /// 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 /// 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. /// 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; virtual void adjustPosition (const MWWorld::Ptr& ptr, bool force) = 0;
///< Adjust position after load to be on ground. Must be called after model load. ///< Adjust position after load to be on ground. Must be called after model load.

View File

@ -238,7 +238,7 @@ namespace MWClass
const float fCombatDistance = gmst.find("fCombatDistance")->getFloat(); const float fCombatDistance = gmst.find("fCombatDistance")->getFloat();
dist = fCombatDistance * weapon.get<ESM::Weapon>()->mBase->mData.mReach; 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()) if (result.first.isEmpty())
return; // Didn't hit anything return; // Didn't hit anything
@ -247,7 +247,7 @@ namespace MWClass
if (!victim.getClass().isActor()) if (!victim.getClass().isActor())
return; // Can't hit non-actors 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); float hitchance = MWMechanics::getHitChance(ptr, victim, ref->mBase->mData.mCombat);

View File

@ -491,9 +491,9 @@ namespace MWClass
store.find("fHandToHandReach")->getFloat()); store.find("fHandToHandReach")->getFloat());
// TODO: Use second to work out the hit angle // 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; 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 if(victim.isEmpty()) // Didn't hit anything
return; return;

View File

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

View File

@ -653,35 +653,78 @@ namespace MWPhysics
return mDebugDrawEnabled; return mDebugDrawEnabled;
} }
std::pair<std::string,Ogre::Vector3> PhysicsSystem::getHitContact(const std::string &name, class DeepestNotMeContactTestResultCallback : public btCollisionWorld::ContactResultCallback
const Ogre::Vector3 &origin, {
const Ogre::Quaternion &orient, 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) float queryDistance)
{ {
return std::make_pair(std::string(), Ogre::Vector3());
/*
const MWWorld::Store<ESM::GameSetting> &store = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); 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(), btConeShape shape (osg::DegreesToRadians(store.find("fCombatAngleXY")->getFloat()/2.0f), queryDistance);
queryDistance); shape.setLocalScaling(btVector3(1, 1, osg::DegreesToRadians(store.find("fCombatAngleZ")->getFloat()/2.0f) /
shape.setLocalScaling(btVector3(1, 1, Ogre::Degree(store.find("fCombatAngleZ")->getFloat()/2.0f).valueRadians() /
shape.getRadius())); shape.getRadius()));
// The shape origin is its center, so we have to move it forward by half the length. The // 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. // 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; btCollisionObject object;
object.setCollisionShape(&shape); object.setCollisionShape(&shape);
object.setWorldTransform(btTransform(btQuaternion(orient.x, orient.y, orient.z, orient.w), object.setWorldTransform(btTransform(toBullet(orient), toBullet(center)));
btVector3(center.x, center.y, center.z)));
std::pair<const OEngine::Physic::RigidBody*,btVector3> result = mEngine->getFilteredContact( const btCollisionObject* me = NULL;
name, btVector3(origin.x, origin.y, origin.z), &object); Actor* physactor = getActor(actor);
if(!result.first) if (physactor)
return std::make_pair(std::string(), Ogre::Vector3(&result.second[0])); me = physactor->getCollisionObject();
return std::make_pair(result.first->mName, Ogre::Vector3(&result.second[0]));
*/ 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());
} }

View File

@ -11,6 +11,8 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include <osg/Quat>
namespace osg namespace osg
{ {
class Group; 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 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); osg::Vec3f traceDown(const MWWorld::Ptr &ptr, float maxHeight);
std::pair<std::string,Ogre::Vector3> getHitContact(const std::string &name, std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::Ptr& actor,
const Ogre::Vector3 &origin, const osg::Vec3f &origin,
const Ogre::Quaternion &orientation, const osg::Quat &orientation,
float queryDistance); float queryDistance);
// cast ray, return true if it hit something. // cast ray, return true if it hit something.

View File

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

View File

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

View File

@ -344,7 +344,7 @@ namespace MWWorld
/// Returns a pointer to the object the provided object would hit (if within the /// 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 /// specified distance), and the point where the hit occurs. This will attempt to
/// use the "Head" node as a basis. /// 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 deleteObject (const Ptr& ptr);
virtual void undeleteObject (const Ptr& ptr); virtual void undeleteObject (const Ptr& ptr);