diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index db34e04117..840bb3bd61 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -396,16 +396,16 @@ namespace MWPhysics if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope && tracer.mHitObject->getBroadphaseHandle()->m_collisionFilterGroup != CollisionType_Actor) { - /* const btCollisionObject* standingOn = tracer.mHitObject; - + /* if (const OEngine::Physic::RigidBody* body = dynamic_cast<const OEngine::Physic::RigidBody*>(standingOn)) { standingCollisionTracker[ptr.getRefData().getHandle()] = body->mName; } + */ + if (standingOn->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Water) physicActor->setWalkingOnWater(true); - */ if (!isFlying) newPosition.z() = tracer.mEndPos.z() + 1.0f; @@ -698,23 +698,21 @@ namespace MWPhysics */ } - std::pair<bool, Ogre::Vector3> - PhysicsSystem::castRay(const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, float len) + std::pair<bool, osg::Vec3f> PhysicsSystem::castRay(const osg::Vec3f &from, const osg::Vec3f &to) { - return std::make_pair(false, Ogre::Vector3()); - /* - Ogre::Ray ray = Ogre::Ray(orig, dir); - Ogre::Vector3 to = ray.getPoint(len); + btVector3 btFrom = toBullet(from); + btVector3 btTo = toBullet(to); - btVector3 btFrom = btVector3(orig.x, orig.y, orig.z); - btVector3 btTo = btVector3(to.x, to.y, to.z); + btCollisionWorld::ClosestRayResultCallback resultCallback(btFrom, btTo); + resultCallback.m_collisionFilterGroup = 0xff; + resultCallback.m_collisionFilterMask = CollisionType_World | CollisionType_HeightMap; - std::pair<std::string, float> test = mEngine->rayTest(btFrom, btTo); - if (test.second == -1) { - return std::make_pair(false, Ogre::Vector3()); + mDynamicsWorld->rayTest(btFrom, btTo, resultCallback); + if (resultCallback.hasHit()) + { + return std::make_pair(true, toOsg(resultCallback.m_hitPointWorld)); } - return std::make_pair(true, ray.getPoint(len * test.second)); - */ + return std::make_pair(false, osg::Vec3f()); } std::vector<std::string> PhysicsSystem::getCollisions(const MWWorld::Ptr &ptr, int collisionGroup, int collisionMask) diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index 91e166bef4..5f89b1b435 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -86,8 +86,8 @@ namespace MWPhysics // cast ray, return true if it hit something. bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to,bool ignoreHeightMap = false); - std::pair<bool, Ogre::Vector3> - castRay(const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, float len); + /// @return <bool hit, world hit position> + std::pair<bool, osg::Vec3f> castRay(const osg::Vec3f &from, const osg::Vec3f &to); /// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will /// be overwritten. Valid until the next call to applyQueuedMovement. diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 110ed61beb..c81a3f71b9 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -10,6 +10,8 @@ #include <OgreSceneNode.h> #include <osg/Group> +#include <osg/ComputeBoundsVisitor> +#include <osg/PositionAttitudeTransform> #include <components/misc/rng.hpp> @@ -1888,29 +1890,6 @@ namespace MWWorld Ptr World::copyObjectToCell(const Ptr &object, CellStore* cell, ESM::Position pos, bool adjustPos) { -#if 0 - if (!object.getClass().isActor() && adjustPos) - { - // Adjust position so the location we wanted ends up in the middle of the object bounding box - Ogre::Vector3 min, max; - if (mPhysics->getObjectAABB(object, min, max)) { - Ogre::Quaternion xr(Ogre::Radian(-pos.rot[0]), Ogre::Vector3::UNIT_X); - Ogre::Quaternion yr(Ogre::Radian(-pos.rot[1]), Ogre::Vector3::UNIT_Y); - Ogre::Quaternion zr(Ogre::Radian(-pos.rot[2]), Ogre::Vector3::UNIT_Z); - - Ogre::Vector3 adjust ( - (min.x + max.x) / 2, - (min.y + max.y) / 2, - min.z - ); - adjust = (xr*yr*zr) * adjust; - pos.pos[0] -= adjust.x; - pos.pos[1] -= adjust.y; - pos.pos[2] -= adjust.z; - } - } -#endif - if (cell->isExterior()) { int cellX, cellY; @@ -1941,6 +1920,28 @@ namespace MWWorld addContainerScripts(dropped, cell); } + if (!object.getClass().isActor() && adjustPos && dropped.getRefData().getBaseNode()) + { + // Adjust position so the location we wanted ends up in the middle of the object bounding box + osg::ComputeBoundsVisitor computeBounds; + dropped.getRefData().getBaseNode()->accept(computeBounds); + osg::BoundingBox bounds = computeBounds.getBoundingBox(); + if (bounds.valid()) + { + bounds.set(bounds._min - pos.asVec3(), bounds._max - pos.asVec3()); + + osg::Vec3f adjust ( + (bounds.xMin() + bounds.xMax()) / 2, + (bounds.yMin() + bounds.yMax()) / 2, + bounds.zMin() + ); + pos.pos[0] -= adjust.x(); + pos.pos[1] -= adjust.y(); + pos.pos[2] -= adjust.z(); + moveObject(dropped, pos.pos[0], pos.pos[1], pos.pos[2]); + } + } + return dropped; } @@ -1954,17 +1955,15 @@ namespace MWWorld pos.rot[0] = 0; pos.rot[1] = 0; - Ogre::Vector3 orig = - Ogre::Vector3(pos.pos); - orig.z += 20; - //Ogre::Vector3 dir = Ogre::Vector3(0, 0, -1); + osg::Vec3f orig = pos.asVec3(); + orig.z() += 20; + osg::Vec3f dir (0, 0, -1); - //float len = 100.0; + float len = 100.0; - std::pair<bool, Ogre::Vector3> hit;// = - //mPhysics->castRay(orig, dir, len); + std::pair<bool, osg::Vec3f> hit = mPhysics->castRay(orig, dir*len); if (hit.first) - pos.pos[2] = hit.second.z; + pos.pos[2] = hit.second.z(); // copy the object and set its count int origCount = object.getRefData().getCount(); @@ -2069,14 +2068,12 @@ namespace MWWorld // TODO: There might be better places to update PhysicActor::mOnGround. bool World::isOnGround(const MWWorld::Ptr &ptr) const { - return true; - /* - //RefData &refdata = ptr.getRefData(); - OEngine::Physic::PhysicActor *physactor = 0;//mPhysEngine->getCharacter(refdata.getHandle()); + MWPhysics::Actor* physactor = mPhysics->getActor(ptr); if(!physactor) return false; - + return physactor->getOnGround(); + /* if(physactor->getOnGround()) return true; else