From 21121d5ba57846b48667fcbb1620f1d60dddbcdb Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 16 Aug 2013 04:18:48 -0700 Subject: [PATCH 1/8] Store the object class in the LiveCellRef --- apps/openmw/mwworld/class.cpp | 5 +++-- apps/openmw/mwworld/class.hpp | 8 +++++++- apps/openmw/mwworld/livecellref.hpp | 7 +++---- apps/openmw/mwworld/ptr.cpp | 15 +++++++++++++++ apps/openmw/mwworld/ptr.hpp | 10 ++++++---- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index c7b8d341c..c739ea831 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -245,9 +245,10 @@ namespace MWWorld throw std::runtime_error ("class does not support persistence"); } - void Class::registerClass (const std::string& key, boost::shared_ptr instance) + void Class::registerClass(const std::string& key, boost::shared_ptr instance) { - sClasses.insert (std::make_pair (key, instance)); + instance->mTypeName = key; + sClasses.insert(std::make_pair(key, instance)); } std::string Class::getUpSoundId (const Ptr& ptr) const diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index c91000052..28e37cbf3 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -50,6 +50,8 @@ namespace MWWorld { static std::map > sClasses; + std::string mTypeName; + // not implemented Class (const Class&); Class& operator= (const Class&); @@ -73,6 +75,10 @@ namespace MWWorld virtual ~Class(); + const std::string& getTypeName() const { + return mTypeName; + } + virtual std::string getId (const Ptr& ptr) const; ///< Return ID of \a ptr or throw an exception, if class does not support ID retrieval /// (default implementation: throw an exception) @@ -292,7 +298,7 @@ namespace MWWorld static const Class& get (const Ptr& ptr) { - return get(ptr.getTypeName()); + return ptr.getClass(); } ///< If there is no class for this pointer, an exception is thrown. diff --git a/apps/openmw/mwworld/livecellref.hpp b/apps/openmw/mwworld/livecellref.hpp index 64462cb3f..415351e78 100644 --- a/apps/openmw/mwworld/livecellref.hpp +++ b/apps/openmw/mwworld/livecellref.hpp @@ -11,11 +11,12 @@ namespace MWWorld { class Ptr; class ESMStore; + class Class; /// Used to create pointers to hold any type of LiveCellRef<> object. struct LiveCellRefBase { - std::string mTypeName; + const Class *mClass; /** Information about this instance, such as 3D location and rotation * and individual type-dependent data. @@ -25,9 +26,7 @@ namespace MWWorld /** runtime-data */ RefData mData; - LiveCellRefBase(std::string type, const ESM::CellRef &cref=ESM::CellRef()) - : mTypeName(type), mRef(cref), mData(mRef) - { } + LiveCellRefBase(std::string type, const ESM::CellRef &cref=ESM::CellRef()); /* Need this for the class to be recognized as polymorphic */ virtual ~LiveCellRefBase() { } }; diff --git a/apps/openmw/mwworld/ptr.cpp b/apps/openmw/mwworld/ptr.cpp index 34fe7fa08..127ab1364 100644 --- a/apps/openmw/mwworld/ptr.cpp +++ b/apps/openmw/mwworld/ptr.cpp @@ -4,8 +4,23 @@ #include #include "containerstore.hpp" +#include "class.hpp" +/* This shouldn't really be here. */ +MWWorld::LiveCellRefBase::LiveCellRefBase(std::string type, const ESM::CellRef &cref) + : mClass(&Class::get(type)), mRef(cref), mData(mRef) +{ +} + + +const std::string& MWWorld::Ptr::getTypeName() const +{ + if(mRef != 0) + return mRef->mClass->getTypeName(); + throw std::runtime_error("Can't get type name from an empty object."); +} + ESM::CellRef& MWWorld::Ptr::getCellRef() const { assert(mRef); diff --git a/apps/openmw/mwworld/ptr.hpp b/apps/openmw/mwworld/ptr.hpp index 51c1530d7..e5352da28 100644 --- a/apps/openmw/mwworld/ptr.hpp +++ b/apps/openmw/mwworld/ptr.hpp @@ -32,11 +32,13 @@ namespace MWWorld return mRef == 0; } - const std::string& getTypeName() const + const std::string& getTypeName() const; + + const Class& getClass() const { if(mRef != 0) - return mRef->mTypeName; - throw std::runtime_error("Can't get type name from an empty object."); + return *(mRef->mClass); + throw std::runtime_error("Cannot get class of an empty object"); } template @@ -47,7 +49,7 @@ namespace MWWorld std::stringstream str; str<< "Bad LiveCellRef cast to "<mTypeName; + if(mRef != 0) str<< getTypeName(); else str<< "an empty object"; throw std::runtime_error(str.str()); From 40fa11577c7a3e43ac013d231e3b1a6c0ddfb605 Mon Sep 17 00:00:00 2001 From: eroen Date: Fri, 16 Aug 2013 22:32:16 +0200 Subject: [PATCH 2/8] Re-introduce lost functionality The branch merged in 5a863589b4 removed fine-grained configure-time control over install paths. This is necessary to accomodate various linux distros' policies, eg. Gentoo wants games installed in /usr/games, but with resource files in /usr/share/games. DOCDIR and MANDIR appear to be unused, and were not re-introduced. --- CMakeLists.txt | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 575fecd0c..85860609b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -334,12 +334,18 @@ IF(NOT WIN32 AND NOT APPLE) IF (DPKG_PROGRAM) ## Debian specific SET(CMAKE_INSTALL_PREFIX "/usr") + SET(DATAROOTDIR "share" CACHE PATH "Sets the root of data directories to a non-default location") + SET(DATADIR "share/games/openmw" CACHE PATH "Sets the openmw data directories to a non-default location") + SET(ICONDIR "share/pixmaps" CACHE PATH "Set icon dir") SET(SYSCONFDIR "../etc/openmw" CACHE PATH "Set config dir") ELSE () ## Non debian specific SET(SYSCONFDIR "/etc/openmw" CACHE PATH "Set config dir") SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries") - SET(LICDIR "${CMAKE_INSTALL_PREFIX}/share/licenses/openmw" CACHE PATH "Sets the openmw license directory to a non-default location.") + SET(DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Sets the root of data directories to a non-default location") + SET(DATADIR "${DATAROOTDIR}/games/openmw" CACHE PATH "Sets the openmw data directories to a non-default location") + SET(ICONDIR "${DATAROOTDIR}/pixmaps" CACHE PATH "Set icon dir") + SET(LICDIR "${DATAROOTDIR}/licenses/openmw" CACHE PATH "Sets the openmw license directory to a non-default location.") # Install binaries INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" ) @@ -367,11 +373,11 @@ IF(NOT WIN32 AND NOT APPLE) ENDIF (DPKG_PROGRAM) # Install icon and desktop file - INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "share/applications/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") - INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "share/pixmaps/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") + INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") + INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") IF(BUILD_OPENCS) - INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.desktop" DESTINATION "share/applications/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs") - INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/opencs.png" DESTINATION "share/pixmaps/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs") + INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.desktop" DESTINATION "${DATAROOTDIR}/applications/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs") + INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/opencs.png" DESTINATION "${ICONDIR}/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs") ENDIF(BUILD_OPENCS) # Install global configuration files @@ -383,8 +389,8 @@ IF(NOT WIN32 AND NOT APPLE) ENDIF(BUILD_OPENCS) # Install resources - INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "share/games/openmw/" FILE_PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT "Resources") - INSTALL(DIRECTORY DESTINATION "share/games/openmw/data/" COMPONENT "Resources") + INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}/" FILE_PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT "Resources") + INSTALL(DIRECTORY DESTINATION "${DATADIR}/data/" COMPONENT "Resources") IF (DPKG_PROGRAM) ## Debian Specific From 1a88e6d859be92dc689bc9e2ebc3dac9286e8586 Mon Sep 17 00:00:00 2001 From: eroen Date: Fri, 16 Aug 2013 22:32:16 +0200 Subject: [PATCH 3/8] cleanup - drop trailing slashes from paths for consistency - sort entries that got unsorted --- CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 85860609b..dd58ed416 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -340,12 +340,12 @@ IF(NOT WIN32 AND NOT APPLE) SET(SYSCONFDIR "../etc/openmw" CACHE PATH "Set config dir") ELSE () ## Non debian specific - SET(SYSCONFDIR "/etc/openmw" CACHE PATH "Set config dir") SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries") SET(DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Sets the root of data directories to a non-default location") SET(DATADIR "${DATAROOTDIR}/games/openmw" CACHE PATH "Sets the openmw data directories to a non-default location") SET(ICONDIR "${DATAROOTDIR}/pixmaps" CACHE PATH "Set icon dir") SET(LICDIR "${DATAROOTDIR}/licenses/openmw" CACHE PATH "Sets the openmw license directory to a non-default location.") + SET(SYSCONFDIR "/etc/openmw" CACHE PATH "Set config dir") # Install binaries INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" ) @@ -373,11 +373,11 @@ IF(NOT WIN32 AND NOT APPLE) ENDIF (DPKG_PROGRAM) # Install icon and desktop file - INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") - INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") + INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") + INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") IF(BUILD_OPENCS) - INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.desktop" DESTINATION "${DATAROOTDIR}/applications/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs") - INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/opencs.png" DESTINATION "${ICONDIR}/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs") + INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.desktop" DESTINATION "${DATAROOTDIR}/applications" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs") + INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/opencs.png" DESTINATION "${ICONDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs") ENDIF(BUILD_OPENCS) # Install global configuration files @@ -389,8 +389,8 @@ IF(NOT WIN32 AND NOT APPLE) ENDIF(BUILD_OPENCS) # Install resources - INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}/" FILE_PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT "Resources") - INSTALL(DIRECTORY DESTINATION "${DATADIR}/data/" COMPONENT "Resources") + INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}" FILE_PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT "Resources") + INSTALL(DIRECTORY DESTINATION "${DATADIR}/data" COMPONENT "Resources") IF (DPKG_PROGRAM) ## Debian Specific From d82f54c771a1664b3a6907ec92230be098a42290 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 17 Aug 2013 01:11:57 -0700 Subject: [PATCH 4/8] Improve actor movement collision handling --- apps/openmw/mwworld/physicssystem.cpp | 127 ++++++++++++-------------- 1 file changed, 56 insertions(+), 71 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 371783bc5..e8450e1d2 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -31,17 +31,22 @@ namespace MWWorld static const float sMaxSlope = 60.0f; static const float sStepSize = 30.0f; // Arbitrary number. To prevent infinite loops. They shouldn't happen but it's good to be prepared. - static const int sMaxIterations = 50; + static const int sMaxIterations = 4; class MovementSolver { private: - static bool stepMove(Ogre::Vector3& position, const Ogre::Quaternion& orient, const Ogre::Vector3 &velocity, float remainingTime, + static float getSlope(const Ogre::Vector3 &normal) + { + return normal.angleBetween(Ogre::Vector3(0.0f,0.0f,1.0f)).valueDegrees(); + } + + static bool stepMove(Ogre::Vector3& position, const Ogre::Quaternion& orient, + const Ogre::Vector3 &velocity, float &remainingTime, const Ogre::Vector3 &halfExtents, bool isInterior, OEngine::Physic::PhysicEngine *engine) { - traceResults trace; // no initialization needed - + traceResults trace; newtrace(&trace, orient, position, position+Ogre::Vector3(0.0f,0.0f,sStepSize), halfExtents, isInterior, engine); if(trace.fraction == 0.0f) @@ -51,44 +56,33 @@ namespace MWWorld halfExtents, isInterior, engine); if(trace.fraction == 0.0f || (trace.fraction != 1.0f && getSlope(trace.planenormal) > sMaxSlope)) return false; + float movefrac = trace.fraction; newtrace(&trace, orient, trace.endpos, trace.endpos-Ogre::Vector3(0.0f,0.0f,sStepSize), halfExtents, isInterior, engine); if(getSlope(trace.planenormal) <= sMaxSlope) { // only step down onto semi-horizontal surfaces. don't step down onto the side of a house or a wall. position = trace.endpos; + remainingTime *= (1.0f-movefrac); return true; } return false; } - static void clipVelocity(Ogre::Vector3& inout, const Ogre::Vector3& normal, float overbounce=1.0f) - { - //Math stuff. Basically just project the velocity vector onto the plane represented by the normal. - //More specifically, it projects velocity onto the normal, takes that result, multiplies it by overbounce and then subtracts it from velocity. - float backoff = inout.dotProduct(normal); - if(backoff < 0.0f) - backoff *= overbounce; - else - backoff /= overbounce; - inout -= normal*backoff; + ///Project a vector u on another vector v + static inline Ogre::Vector3 project(const Ogre::Vector3 u, const Ogre::Vector3 &v) + { + return v * u.dotProduct(v); } - static void projectVelocity(Ogre::Vector3& velocity, const Ogre::Vector3& direction) + ///Helper for computing the character sliding + static inline Ogre::Vector3 slide(Ogre::Vector3 direction, const Ogre::Vector3 &planeNormal) { - Ogre::Vector3 normalizedDirection(direction); - normalizedDirection.normalise(); - - // no divide by normalizedDirection.length necessary because it's normalized - velocity = normalizedDirection * velocity.dotProduct(normalizedDirection); + return direction - project(direction, planeNormal); } - static float getSlope(const Ogre::Vector3 &normal) - { - return normal.angleBetween(Ogre::Vector3(0.0f,0.0f,1.0f)).valueDegrees(); - } public: static Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr, OEngine::Physic::PhysicEngine *engine) @@ -104,7 +98,6 @@ namespace MWWorld return position; bool wasCollisionMode = physicActor->getCollisionMode(); - physicActor->enableCollisions(false); Ogre::Vector3 halfExtents = physicActor->getHalfExtents();// + Vector3(1,1,1); @@ -124,10 +117,9 @@ namespace MWWorld if (wasCollisionMode) physicActor->enableCollisions(true); - if (hit) - return newPosition+Ogre::Vector3(0,0,4); - else + if(!hit) return position; + return newPosition+Ogre::Vector3(0,0,4); } static Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time, @@ -147,14 +139,13 @@ namespace MWWorld movement; } - traceResults trace; //no initialization needed - bool onground = false; - float remainingTime = time; bool isInterior = !ptr.getCell()->isExterior(); Ogre::Vector3 halfExtents = physicActor->getHalfExtents();// + Vector3(1,1,1); - bool wasCollisionMode = physicActor->getCollisionMode(); physicActor->enableCollisions(false); - Ogre::Quaternion orient = Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::UNIT_Z); + + traceResults trace; + bool onground = false; + const Ogre::Quaternion orient; // Don't rotate actor collision boxes Ogre::Vector3 velocity; if(!gravity) { @@ -175,53 +166,46 @@ namespace MWWorld velocity.z += physicActor->getVerticalForce(); } - Ogre::Vector3 clippedVelocity(velocity); if(onground) { - // if we're on the ground, force velocity to track it - clippedVelocity.z = velocity.z = std::max(0.0f, velocity.z); - clipVelocity(clippedVelocity, trace.planenormal); + // if we're on the ground, don't try to fall + velocity.z = std::max(0.0f, velocity.z); } const Ogre::Vector3 up(0.0f, 0.0f, 1.0f); Ogre::Vector3 newPosition = position; - int iterations = 0; - do { + float remainingTime = time; + for(int iterations = 0;iterations < sMaxIterations && remainingTime > 0.01f;++iterations) + { // trace to where character would go if there were no obstructions - newtrace(&trace, orient, newPosition, newPosition+clippedVelocity*remainingTime, halfExtents, isInterior, engine); - newPosition = trace.endpos; - remainingTime = remainingTime * (1.0f-trace.fraction); + newtrace(&trace, orient, newPosition, newPosition+velocity*remainingTime, halfExtents, isInterior, engine); // check for obstructions - if(trace.fraction < 1.0f) + if(trace.fraction >= 1.0f) { - //std::cout<<"angle: "< 0.0f); + //std::cout<<"angle: "<setOnGround(onground); - physicActor->setVerticalForce(!onground ? clippedVelocity.z - time*627.2f : 0.0f); - if (wasCollisionMode) - physicActor->enableCollisions(true); + physicActor->setVerticalForce(!onground ? velocity.z - time*627.2f : 0.0f); + physicActor->enableCollisions(true); + return newPosition; } }; From 65ce3c6ba5512885d1e0b252f539a4e66d084d82 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 17 Aug 2013 02:51:19 -0700 Subject: [PATCH 5/8] Use a better method to do actor physics traces --- apps/openmw/mwworld/physicssystem.cpp | 35 ++++++------ libs/openengine/bullet/physic.hpp | 48 +++++++++------- libs/openengine/bullet/trace.cpp | 82 +++++++++++++++++++++++++-- libs/openengine/bullet/trace.h | 4 ++ 4 files changed, 124 insertions(+), 45 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index e8450e1d2..ea013bc7a 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -41,24 +41,21 @@ namespace MWWorld return normal.angleBetween(Ogre::Vector3(0.0f,0.0f,1.0f)).valueDegrees(); } - static bool stepMove(Ogre::Vector3& position, const Ogre::Quaternion& orient, + static bool stepMove(btCollisionObject *colobj, Ogre::Vector3 &position, const Ogre::Vector3 &velocity, float &remainingTime, - const Ogre::Vector3 &halfExtents, bool isInterior, OEngine::Physic::PhysicEngine *engine) { traceResults trace; - newtrace(&trace, orient, position, position+Ogre::Vector3(0.0f,0.0f,sStepSize), - halfExtents, isInterior, engine); + actortrace(&trace, colobj, position, position+Ogre::Vector3(0.0f,0.0f,sStepSize), engine); if(trace.fraction == 0.0f) return false; - newtrace(&trace, orient, trace.endpos, trace.endpos + velocity*remainingTime, - halfExtents, isInterior, engine); + actortrace(&trace, colobj, trace.endpos, trace.endpos + velocity*remainingTime, engine); if(trace.fraction == 0.0f || (trace.fraction != 1.0f && getSlope(trace.planenormal) > sMaxSlope)) return false; float movefrac = trace.fraction; - newtrace(&trace, orient, trace.endpos, trace.endpos-Ogre::Vector3(0.0f,0.0f,sStepSize), halfExtents, isInterior, engine); + actortrace(&trace, colobj, trace.endpos, trace.endpos-Ogre::Vector3(0.0f,0.0f,sStepSize), engine); if(getSlope(trace.planenormal) <= sMaxSlope) { // only step down onto semi-horizontal surfaces. don't step down onto the side of a house or a wall. @@ -100,7 +97,7 @@ namespace MWWorld bool wasCollisionMode = physicActor->getCollisionMode(); physicActor->enableCollisions(false); - Ogre::Vector3 halfExtents = physicActor->getHalfExtents();// + Vector3(1,1,1); + Ogre::Vector3 halfExtents = physicActor->getHalfExtents(); halfExtents.z = 1; // we trace the feet only, so we use a very thin box Ogre::Vector3 newPosition = position; @@ -133,15 +130,15 @@ namespace MWWorld if(!physicActor || !physicActor->getCollisionMode()) { // FIXME: This works, but it's inconcsistent with how the rotations are applied elsewhere. Why? - return position + (Ogre::Quaternion(Ogre::Radian( -refpos.rot[2]), Ogre::Vector3::UNIT_Z)* - Ogre::Quaternion(Ogre::Radian( -refpos.rot[1]), Ogre::Vector3::UNIT_Y)* - Ogre::Quaternion(Ogre::Radian( refpos.rot[0]), Ogre::Vector3::UNIT_X)) * + return position + (Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z)* + Ogre::Quaternion(Ogre::Radian(-refpos.rot[1]), Ogre::Vector3::UNIT_Y)* + Ogre::Quaternion(Ogre::Radian( refpos.rot[0]), Ogre::Vector3::UNIT_X)) * movement; } - bool isInterior = !ptr.getCell()->isExterior(); - Ogre::Vector3 halfExtents = physicActor->getHalfExtents();// + Vector3(1,1,1); - physicActor->enableCollisions(false); + btCollisionObject *colobj = physicActor->getCollisionBody(); + Ogre::Vector3 halfExtents = physicActor->getHalfExtents(); + position.z += halfExtents.z; traceResults trace; bool onground = false; @@ -158,7 +155,7 @@ namespace MWWorld { if(!(movement.z > 0.0f)) { - newtrace(&trace, orient, position, position-Ogre::Vector3(0,0,4), halfExtents, isInterior, engine); + actortrace(&trace, colobj, position, position-Ogre::Vector3(0,0,4), engine); if(trace.fraction < 1.0f && getSlope(trace.planenormal) <= sMaxSlope) onground = true; } @@ -178,7 +175,7 @@ namespace MWWorld for(int iterations = 0;iterations < sMaxIterations && remainingTime > 0.01f;++iterations) { // trace to where character would go if there were no obstructions - newtrace(&trace, orient, newPosition, newPosition+velocity*remainingTime, halfExtents, isInterior, engine); + actortrace(&trace, colobj, newPosition, newPosition+velocity*remainingTime, engine); // check for obstructions if(trace.fraction >= 1.0f) @@ -190,7 +187,7 @@ namespace MWWorld //std::cout<<"angle: "<setOnGround(onground); physicActor->setVerticalForce(!onground ? velocity.z - time*627.2f : 0.0f); - physicActor->enableCollisions(true); + newPosition.z -= halfExtents.z; return newPosition; } }; diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 32af0da4e..9b1541ea2 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -66,6 +66,20 @@ namespace Physic std::string mName; }; + /** + *This class is just an extension of normal btRigidBody in order to add extra info. + *When bullet give back a btRigidBody, you can just do a static_cast to RigidBody, + *so one never should use btRigidBody directly! + */ + class RigidBody: public btRigidBody + { + public: + RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name); + virtual ~RigidBody(); + std::string mName; + bool mPlaceable; + }; + /** * A physic actor uses a rigid body based on box shapes. * Pmove is used to move the physic actor around the dynamic world. @@ -129,47 +143,41 @@ namespace Physic bool getOnGround() const; + btCollisionObject *getCollisionBody() const + { + return mBody; + } + private: void disableCollisionBody(); void enableCollisionBody(); public: //HACK: in Visual Studio 2010 and presumably above, this structures alignment -// must be 16, but the built in operator new & delete don't properly -// perform this alignment. +// must be 16, but the built in operator new & delete don't properly +// perform this alignment. #if _MSC_VER >= 1600 - void * operator new (size_t Size) { return _aligned_malloc (Size, 16); } - void operator delete (void * Data) { _aligned_free (Data); } + void * operator new (size_t Size) { return _aligned_malloc (Size, 16); } + void operator delete (void * Data) { _aligned_free (Data); } #endif private: - OEngine::Physic::RigidBody* mBody; OEngine::Physic::RigidBody* mRaycastingBody; + Ogre::Vector3 mBoxScaledTranslation; - btQuaternion mBoxRotationInverse; Ogre::Quaternion mBoxRotation; + btQuaternion mBoxRotationInverse; + float verticalForce; bool onGround; bool collisionMode; + std::string mMesh; - PhysicEngine* mEngine; std::string mName; + PhysicEngine *mEngine; }; - /** - *This class is just an extension of normal btRigidBody in order to add extra info. - *When bullet give back a btRigidBody, you can just do a static_cast to RigidBody, - *so one never should use btRigidBody directly! - */ - class RigidBody: public btRigidBody - { - public: - RigidBody(btRigidBody::btRigidBodyConstructionInfo& CI,std::string name); - virtual ~RigidBody(); - std::string mName; - bool mPlaceable; - }; struct HeightField { diff --git a/libs/openengine/bullet/trace.cpp b/libs/openengine/bullet/trace.cpp index d246417c7..08c42d9d0 100644 --- a/libs/openengine/bullet/trace.cpp +++ b/libs/openengine/bullet/trace.cpp @@ -8,12 +8,6 @@ #include "physic.hpp" -enum traceWorldType -{ - collisionWorldTrace = 1, - pickWorldTrace = 2, - bothWorldTrace = collisionWorldTrace | pickWorldTrace -}; void newtrace(traceResults *results, const Ogre::Quaternion& orient, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, bool isInterior, OEngine::Physic::PhysicEngine *enginePass) //Traceobj was a Aedra Object { @@ -46,3 +40,79 @@ void newtrace(traceResults *results, const Ogre::Quaternion& orient, const Ogre: results->fraction = 1.0f; } } + + +class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback +{ +public: + ClosestNotMeConvexResultCallback(btCollisionObject *me, const btVector3 &up, btScalar minSlopeDot) + : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)), + mMe(me), mUp(up), mMinSlopeDot(minSlopeDot) + { + } + + virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace) + { + if(convexResult.m_hitCollisionObject == mMe) + return btScalar( 1 ); + + btVector3 hitNormalWorld; + if(normalInWorldSpace) + hitNormalWorld = convexResult.m_hitNormalLocal; + else + { + ///need to transform normal into worldspace + hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; + } + + // NOTE : m_hitNormalLocal is not always vertical on the ground with a capsule or a box... + + btScalar dotUp = mUp.dot(hitNormalWorld); + if(dotUp < mMinSlopeDot) + return btScalar(1); + + return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace); + } + +protected: + btCollisionObject *mMe; + const btVector3 mUp; + const btScalar mMinSlopeDot; +}; + +void actortrace(traceResults *results, btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end, OEngine::Physic::PhysicEngine *enginePass) +{ + const btVector3 btstart(start.x, start.y, start.z); + const btVector3 btend(end.x, end.y, end.z); + + const btTransform &trans = actor->getWorldTransform(); + btTransform from(trans); + btTransform to(trans); + from.setOrigin(btstart); + to.setOrigin(btend); + + ClosestNotMeConvexResultCallback newTraceCallback(actor, btstart-btend, btScalar(0.0)); + newTraceCallback.m_collisionFilterMask = OEngine::Physic::CollisionType_World | + OEngine::Physic::CollisionType_HeightMap | + OEngine::Physic::CollisionType_Actor; + + btCollisionShape *shape = actor->getCollisionShape(); + assert(shape->isConvex()); + enginePass->dynamicsWorld->convexSweepTest(static_cast(shape), + from, to, newTraceCallback); + + // Copy the hit data over to our trace results struct: + if(newTraceCallback.hasHit()) + { + const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld; + results->fraction = newTraceCallback.m_closestHitFraction; + results->planenormal = Ogre::Vector3(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z()); + results->endpos = (end-start)*results->fraction + start; + } + else + { + results->endpos = end; + results->planenormal = Ogre::Vector3(0.0f, 0.0f, 1.0f); + results->fraction = 1.0f; + } +} diff --git a/libs/openengine/bullet/trace.h b/libs/openengine/bullet/trace.h index cd2547f8c..79c6e72ef 100644 --- a/libs/openengine/bullet/trace.h +++ b/libs/openengine/bullet/trace.h @@ -13,6 +13,9 @@ namespace OEngine } +class btCollisionObject; + + struct traceResults { Ogre::Vector3 endpos; @@ -22,5 +25,6 @@ struct traceResults }; void newtrace(traceResults *results, const Ogre::Quaternion& orient, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, bool isInterior, OEngine::Physic::PhysicEngine* enginePass); +void actortrace(traceResults *results, btCollisionObject *actor, const Ogre::Vector3& start, const Ogre::Vector3& end, OEngine::Physic::PhysicEngine *enginePass); #endif From 62c7b3698d47cdfb28486249458286d1a6bab318 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 17 Aug 2013 03:55:04 -0700 Subject: [PATCH 6/8] Get rid of the old newtrace method --- apps/openmw/mwworld/physicssystem.cpp | 37 ++++++++++----------------- libs/openengine/bullet/trace.cpp | 35 +------------------------ libs/openengine/bullet/trace.h | 1 - 3 files changed, 14 insertions(+), 59 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index ea013bc7a..65cc806ea 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -87,36 +87,25 @@ namespace MWWorld const ESM::Position &refpos = ptr.getRefData().getPosition(); Ogre::Vector3 position(refpos.pos); - bool hit=false; - bool isInterior = !ptr.getCell()->isExterior(); - OEngine::Physic::PhysicActor *physicActor = engine->getCharacter(ptr.getRefData().getHandle()); if (!physicActor) return position; - bool wasCollisionMode = physicActor->getCollisionMode(); - physicActor->enableCollisions(false); + const int maxHeight = 64.f; + Ogre::Vector3 newPosition = position+Ogre::Vector3(0.0f, 0.0f, 4.0f); - Ogre::Vector3 halfExtents = physicActor->getHalfExtents(); - halfExtents.z = 1; // we trace the feet only, so we use a very thin box - - Ogre::Vector3 newPosition = position; - - traceResults trace; //no initialization needed - - int maxHeight = 200.f; - newtrace(&trace, Ogre::Quaternion::IDENTITY, newPosition, newPosition-Ogre::Vector3(0,0,maxHeight), halfExtents, isInterior, engine); - if(trace.fraction < 1.0f) - hit = true; - newPosition = trace.endpos; - - physicActor->setOnGround(hit && getSlope(trace.planenormal) <= sMaxSlope); - if (wasCollisionMode) - physicActor->enableCollisions(true); - - if(!hit) + traceResults trace; + actortrace(&trace, physicActor->getCollisionBody(), newPosition, newPosition-Ogre::Vector3(0,0,maxHeight), engine); + if(trace.fraction >= 1.0f) return position; - return newPosition+Ogre::Vector3(0,0,4); + + physicActor->setOnGround(getSlope(trace.planenormal) <= sMaxSlope); + + newPosition = trace.endpos; + newPosition.z -= physicActor->getHalfExtents().z; + newPosition.z += 4.0f; + + return newPosition; } static Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time, diff --git a/libs/openengine/bullet/trace.cpp b/libs/openengine/bullet/trace.cpp index 08c42d9d0..744462a0c 100644 --- a/libs/openengine/bullet/trace.cpp +++ b/libs/openengine/bullet/trace.cpp @@ -9,39 +9,6 @@ #include "physic.hpp" -void newtrace(traceResults *results, const Ogre::Quaternion& orient, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, bool isInterior, OEngine::Physic::PhysicEngine *enginePass) //Traceobj was a Aedra Object -{ - const btVector3 btstart(start.x, start.y, start.z + BBHalfExtents.z); - const btVector3 btend(end.x, end.y, end.z + BBHalfExtents.z); - const btQuaternion btorient (orient.x, orient.y, orient.z, orient.w); - - const btBoxShape newshape(btVector3(BBHalfExtents.x, BBHalfExtents.y, BBHalfExtents.z)); - //const btCapsuleShapeZ newshape(BBHalfExtents.x, BBHalfExtents.z * 2 - BBHalfExtents.x * 2); - const btTransform from(btorient, btstart); - const btTransform to(btorient, btend); - - btCollisionWorld::ClosestConvexResultCallback newTraceCallback(btstart, btend); - newTraceCallback.m_collisionFilterMask = OEngine::Physic::CollisionType_World|OEngine::Physic::CollisionType_HeightMap|OEngine::Physic::CollisionType_Actor; - - enginePass->dynamicsWorld->convexSweepTest(&newshape, from, to, newTraceCallback); - - // Copy the hit data over to our trace results struct: - if(newTraceCallback.hasHit()) - { - const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld; - results->fraction = newTraceCallback.m_closestHitFraction; - results->planenormal = Ogre::Vector3(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z()); - results->endpos = (end-start)*results->fraction + start; - } - else - { - results->endpos = end; - results->planenormal = Ogre::Vector3(0.0f, 0.0f, 1.0f); - results->fraction = 1.0f; - } -} - - class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback { public: @@ -62,7 +29,7 @@ public: else { ///need to transform normal into worldspace - hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; + hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; } // NOTE : m_hitNormalLocal is not always vertical on the ground with a capsule or a box... diff --git a/libs/openengine/bullet/trace.h b/libs/openengine/bullet/trace.h index 79c6e72ef..6353d6cfa 100644 --- a/libs/openengine/bullet/trace.h +++ b/libs/openengine/bullet/trace.h @@ -24,7 +24,6 @@ struct traceResults float fraction; }; -void newtrace(traceResults *results, const Ogre::Quaternion& orient, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, bool isInterior, OEngine::Physic::PhysicEngine* enginePass); void actortrace(traceResults *results, btCollisionObject *actor, const Ogre::Vector3& start, const Ogre::Vector3& end, OEngine::Physic::PhysicEngine *enginePass); #endif From 8bcce0fb556b0f66d80fc345fb67735064c76461 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 17 Aug 2013 04:42:35 -0700 Subject: [PATCH 7/8] Clean up the trace struct --- apps/openmw/mwworld/physicssystem.cpp | 55 ++++++++++++++------------- libs/openengine/bullet/trace.cpp | 23 +++++++---- libs/openengine/bullet/trace.h | 30 +++++++-------- 3 files changed, 59 insertions(+), 49 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 65cc806ea..ee6514590 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -45,21 +45,22 @@ namespace MWWorld const Ogre::Vector3 &velocity, float &remainingTime, OEngine::Physic::PhysicEngine *engine) { - traceResults trace; - actortrace(&trace, colobj, position, position+Ogre::Vector3(0.0f,0.0f,sStepSize), engine); - if(trace.fraction == 0.0f) + OEngine::Physic::ActorTracer tracer; + tracer.doTrace(colobj, position, position+Ogre::Vector3(0.0f,0.0f,sStepSize), engine); + if(tracer.mFraction == 0.0f) return false; - actortrace(&trace, colobj, trace.endpos, trace.endpos + velocity*remainingTime, engine); - if(trace.fraction == 0.0f || (trace.fraction != 1.0f && getSlope(trace.planenormal) > sMaxSlope)) + tracer.doTrace(colobj, tracer.mEndPos, tracer.mEndPos + velocity*remainingTime, engine); + if(tracer.mFraction < std::numeric_limits::epsilon() || + (tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) > sMaxSlope)) return false; - float movefrac = trace.fraction; + float movefrac = tracer.mFraction; - actortrace(&trace, colobj, trace.endpos, trace.endpos-Ogre::Vector3(0.0f,0.0f,sStepSize), engine); - if(getSlope(trace.planenormal) <= sMaxSlope) + tracer.doTrace(colobj, tracer.mEndPos, tracer.mEndPos-Ogre::Vector3(0.0f,0.0f,sStepSize), engine); + if(getSlope(tracer.mPlaneNormal) <= sMaxSlope) { // only step down onto semi-horizontal surfaces. don't step down onto the side of a house or a wall. - position = trace.endpos; + position = tracer.mEndPos; remainingTime *= (1.0f-movefrac); return true; } @@ -94,16 +95,16 @@ namespace MWWorld const int maxHeight = 64.f; Ogre::Vector3 newPosition = position+Ogre::Vector3(0.0f, 0.0f, 4.0f); - traceResults trace; - actortrace(&trace, physicActor->getCollisionBody(), newPosition, newPosition-Ogre::Vector3(0,0,maxHeight), engine); - if(trace.fraction >= 1.0f) + OEngine::Physic::ActorTracer tracer; + tracer.doTrace(physicActor->getCollisionBody(), newPosition, newPosition-Ogre::Vector3(0,0,maxHeight), engine); + if(tracer.mFraction >= 1.0f) return position; - physicActor->setOnGround(getSlope(trace.planenormal) <= sMaxSlope); + physicActor->setOnGround(getSlope(tracer.mPlaneNormal) <= sMaxSlope); - newPosition = trace.endpos; + newPosition = tracer.mEndPos; newPosition.z -= physicActor->getHalfExtents().z; - newPosition.z += 4.0f; + newPosition.z += 2.0f; return newPosition; } @@ -129,7 +130,7 @@ namespace MWWorld Ogre::Vector3 halfExtents = physicActor->getHalfExtents(); position.z += halfExtents.z; - traceResults trace; + OEngine::Physic::ActorTracer tracer; bool onground = false; const Ogre::Quaternion orient; // Don't rotate actor collision boxes Ogre::Vector3 velocity; @@ -144,8 +145,8 @@ namespace MWWorld { if(!(movement.z > 0.0f)) { - actortrace(&trace, colobj, position, position-Ogre::Vector3(0,0,4), engine); - if(trace.fraction < 1.0f && getSlope(trace.planenormal) <= sMaxSlope) + tracer.doTrace(colobj, position, position-Ogre::Vector3(0,0,4), engine); + if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope) onground = true; } velocity = Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z)*movement / time; @@ -164,13 +165,13 @@ namespace MWWorld for(int iterations = 0;iterations < sMaxIterations && remainingTime > 0.01f;++iterations) { // trace to where character would go if there were no obstructions - actortrace(&trace, colobj, newPosition, newPosition+velocity*remainingTime, engine); + tracer.doTrace(colobj, newPosition, newPosition+velocity*remainingTime, engine); // check for obstructions - if(trace.fraction >= 1.0f) + if(tracer.mFraction >= 1.0f) { - newPosition = trace.endpos; - remainingTime *= (1.0f-trace.fraction); + newPosition = tracer.mEndPos; + remainingTime *= (1.0f-tracer.mFraction); break; } @@ -182,9 +183,9 @@ namespace MWWorld { // Can't move this way, try to find another spot along the plane Ogre::Real movelen = velocity.normalise(); - Ogre::Vector3 reflectdir = velocity.reflect(trace.planenormal); + Ogre::Vector3 reflectdir = velocity.reflect(tracer.mPlaneNormal); reflectdir.normalise(); - velocity = slide(reflectdir, trace.planenormal)*movelen; + velocity = slide(reflectdir, tracer.mPlaneNormal)*movelen; // Do not allow sliding upward if there is gravity. Stepping will have taken // care of that. @@ -195,9 +196,9 @@ namespace MWWorld if(onground) { - actortrace(&trace, colobj, newPosition, newPosition-Ogre::Vector3(0,0,sStepSize+4.0f), engine); - if(trace.fraction < 1.0f && getSlope(trace.planenormal) <= sMaxSlope) - newPosition.z = trace.endpos.z + 2.0f; + tracer.doTrace(colobj, newPosition, newPosition-Ogre::Vector3(0,0,sStepSize+4.0f), engine); + if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope) + newPosition.z = tracer.mEndPos.z + 2.0f; else onground = false; } diff --git a/libs/openengine/bullet/trace.cpp b/libs/openengine/bullet/trace.cpp index 744462a0c..5edf53620 100644 --- a/libs/openengine/bullet/trace.cpp +++ b/libs/openengine/bullet/trace.cpp @@ -9,6 +9,11 @@ #include "physic.hpp" +namespace OEngine +{ +namespace Physic +{ + class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback { public: @@ -47,7 +52,8 @@ protected: const btScalar mMinSlopeDot; }; -void actortrace(traceResults *results, btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end, OEngine::Physic::PhysicEngine *enginePass) + +void ActorTracer::doTrace(btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end, const PhysicEngine *enginePass) { const btVector3 btstart(start.x, start.y, start.z); const btVector3 btend(end.x, end.y, end.z); @@ -72,14 +78,17 @@ void actortrace(traceResults *results, btCollisionObject *actor, const Ogre::Vec if(newTraceCallback.hasHit()) { const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld; - results->fraction = newTraceCallback.m_closestHitFraction; - results->planenormal = Ogre::Vector3(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z()); - results->endpos = (end-start)*results->fraction + start; + mFraction = newTraceCallback.m_closestHitFraction; + mPlaneNormal = Ogre::Vector3(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z()); + mEndPos = (end-start)*mFraction + start; } else { - results->endpos = end; - results->planenormal = Ogre::Vector3(0.0f, 0.0f, 1.0f); - results->fraction = 1.0f; + mEndPos = end; + mPlaneNormal = Ogre::Vector3(0.0f, 0.0f, 1.0f); + mFraction = 1.0f; } } + +} +} diff --git a/libs/openengine/bullet/trace.h b/libs/openengine/bullet/trace.h index 6353d6cfa..f81579c2e 100644 --- a/libs/openengine/bullet/trace.h +++ b/libs/openengine/bullet/trace.h @@ -4,26 +4,26 @@ #include -namespace OEngine -{ - namespace Physic - { - class PhysicEngine; - } -} - - class btCollisionObject; -struct traceResults +namespace OEngine { - Ogre::Vector3 endpos; - Ogre::Vector3 planenormal; +namespace Physic +{ + class PhysicEngine; - float fraction; -}; + struct ActorTracer + { + Ogre::Vector3 mEndPos; + Ogre::Vector3 mPlaneNormal; -void actortrace(traceResults *results, btCollisionObject *actor, const Ogre::Vector3& start, const Ogre::Vector3& end, OEngine::Physic::PhysicEngine *enginePass); + float mFraction; + + void doTrace(btCollisionObject *actor, const Ogre::Vector3 &start, const Ogre::Vector3 &end, + const PhysicEngine *enginePass); + }; +} +} #endif From 0481e64b0211310537de877b9e080c2d83ee0646 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 17 Aug 2013 04:55:35 -0700 Subject: [PATCH 8/8] Fix tracing down --- apps/openmw/mwworld/physicssystem.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index ee6514590..1beb5a7e5 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -92,9 +92,10 @@ namespace MWWorld if (!physicActor) return position; - const int maxHeight = 64.f; - Ogre::Vector3 newPosition = position+Ogre::Vector3(0.0f, 0.0f, 4.0f); + const Ogre::Vector3 halfExtents = physicActor->getHalfExtents(); + Ogre::Vector3 newPosition = position+Ogre::Vector3(0.0f, 0.0f, halfExtents.z); + const int maxHeight = 200.f; OEngine::Physic::ActorTracer tracer; tracer.doTrace(physicActor->getCollisionBody(), newPosition, newPosition-Ogre::Vector3(0,0,maxHeight), engine); if(tracer.mFraction >= 1.0f) @@ -103,7 +104,7 @@ namespace MWWorld physicActor->setOnGround(getSlope(tracer.mPlaneNormal) <= sMaxSlope); newPosition = tracer.mEndPos; - newPosition.z -= physicActor->getHalfExtents().z; + newPosition.z -= halfExtents.z; newPosition.z += 2.0f; return newPosition;