From 006f25d1c04f25542c83ed488202223b786d1829 Mon Sep 17 00:00:00 2001 From: gus Date: Mon, 6 May 2013 00:46:50 +0100 Subject: [PATCH] First try to improve AI. Does not work yet due to strange bug in physicsystem --- apps/openmw/mwbase/world.hpp | 3 +++ apps/openmw/mwmechanics/pathfinding.cpp | 23 ++++++++++++++++------- apps/openmw/mwworld/physicssystem.cpp | 8 +++++--- apps/openmw/mwworld/physicssystem.hpp | 4 ++-- apps/openmw/mwworld/worldimp.cpp | 7 +++++++ apps/openmw/mwworld/worldimp.hpp | 3 +++ libs/openengine/bullet/physic.cpp | 15 +++++++++------ libs/openengine/bullet/physic.hpp | 4 ++-- 8 files changed, 47 insertions(+), 20 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 6c9fa6703..8d71b37cc 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -245,6 +245,9 @@ namespace MWBase virtual void doPhysics (const MWWorld::PtrMovementList &actors, float duration) = 0; ///< Run physics simulation and modify \a world accordingly. + virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2) = 0; + ///< cast a Ray and return true if there is an object in the ray path. + virtual bool toggleCollisionMode() = 0; ///< Toggle collision mode for player. If disabled player object should ignore /// collisions and gravity. diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 2f27d25f8..3f175e00e 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -1,4 +1,8 @@ #include "pathfinding.hpp" + +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" + #include #include #include "boost/tuple/tuple.hpp" @@ -169,15 +173,20 @@ namespace MWMechanics void PathFinder::buildPath(ESM::Pathgrid::Point startPoint,ESM::Pathgrid::Point endPoint, const ESM::Pathgrid* pathGrid,float xCell,float yCell) { - int start = getClosestPoint(pathGrid,startPoint.mX - xCell,startPoint.mY - yCell,startPoint.mZ); - int end = getClosestPoint(pathGrid,endPoint.mX - xCell,endPoint.mY - yCell,endPoint.mZ); - - if(start != -1 && end != -1) + //first check if there is an obstacle + if(MWBase::Environment::get().getWorld()->castRay(startPoint.mX,startPoint.mY,startPoint.mZ, + endPoint.mX,endPoint.mY,endPoint.mZ) ) { - PathGridGraph graph = buildGraph(pathGrid,xCell,yCell); - mPath = findPath(start,end,graph); - } + std::cout << "hit"; + int start = getClosestPoint(pathGrid,startPoint.mX - xCell,startPoint.mY - yCell,startPoint.mZ); + int end = getClosestPoint(pathGrid,endPoint.mX - xCell,endPoint.mY - yCell,endPoint.mZ); + if(start != -1 && end != -1) + { + PathGridGraph graph = buildGraph(pathGrid,xCell,yCell); + mPath = findPath(start,end,graph); + } + } mPath.push_back(endPoint); mIsPathConstructed = true; } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 7abe94aa6..8b6de6804 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -333,14 +333,14 @@ namespace MWWorld return result; } - bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to) + bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to, bool raycastingObjectOnly) { btVector3 _from, _to; _from = btVector3(from.x, from.y, from.z); _to = btVector3(to.x, to.y, to.z); - std::pair result = mEngine->rayTest(_from, _to); - + std::pair result = mEngine->rayTest(_from, _to, false);//raycastingObjectOnly); + std::cout << result.first << " " << result.second; return !(result.first == ""); } @@ -419,6 +419,7 @@ namespace MWWorld OEngine::Physic::RigidBody* raycastingBody = mEngine->createAndAdjustRigidBody( mesh, node->getName(), node->getScale().x, node->getPosition(), node->getOrientation(), 0, 0, true, placeable); mEngine->addRigidBody(body, true, raycastingBody); + std::cout << "Object:" << mesh; } void PhysicsSystem::addActor (const Ptr& ptr) @@ -427,6 +428,7 @@ namespace MWWorld Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); //TODO:optimize this. Searching the std::map isn't very efficient i think. mEngine->addCharacter(node->getName(), mesh, node->getPosition(), node->getScale().x, node->getOrientation()); + std::cout << "Actor:" << mesh; } void PhysicsSystem::removeObject (const std::string& handle) diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 3322c38a6..ad8eb2eba 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -62,8 +62,8 @@ namespace MWWorld btVector3 getRayPoint(float extent, float mouseX, float mouseY); - // cast ray, return true if it hit something - bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to); + // cast ray, return true if it hit something. if raycasringObjectOnlt is set to false, it ignores NPCs and objects with no collisions. + bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to, bool raycastingObjectOnly = true); std::pair castRay(const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, float len); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index d2a6d9af6..a40889515 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1042,6 +1042,13 @@ namespace MWWorld mPhysEngine->stepSimulation (duration); } + bool World::castRay (float x1, float y1, float z1, float x2, float y2, float z2) + { + Ogre::Vector3 a(x1,y1,z1);std::cout << x1 << " " << x2; + Ogre::Vector3 b(x2,y2,z2); + return mPhysics->castRay(a,b,false); + } + void World::processDoors(float duration) { std::map::iterator it = mDoorStates.begin(); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index dadb701f5..2466edd0f 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -279,6 +279,9 @@ namespace MWWorld virtual void doPhysics(const PtrMovementList &actors, float duration); ///< Run physics simulation and modify \a world accordingly. + virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2); + ///< cast a Ray and return true if there is an object in the ray path. + virtual bool toggleCollisionMode(); ///< Toggle collision mode for player. If disabled player object should ignore /// collisions and gravity. diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 2b59e0aad..e6fd18ea2 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -28,7 +28,7 @@ namespace Physic mRaycastingBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation, true); Ogre::Quaternion inverse = mBoxRotation.Inverse(); mBoxRotationInverse = btQuaternion(inverse.x, inverse.y, inverse.z,inverse.w); - mEngine->addRigidBody(mBody, false, mRaycastingBody); //Add rigid body to dynamics world, but do not add to object map + //mEngine->addRigidBody(mBody, false, mRaycastingBody,true); //Add rigid body to dynamics world, but do not add to object map } PhysicActor::~PhysicActor() @@ -422,15 +422,17 @@ namespace Physic } - void PhysicEngine::addRigidBody(RigidBody* body, bool addToMap, RigidBody* raycastingBody) + void PhysicEngine::addRigidBody(RigidBody* body, bool addToMap, RigidBody* raycastingBody,bool actor) { if(!body && !raycastingBody) return; // nothing to do const std::string& name = (body ? body->mName : raycastingBody->mName); - if (body) - dynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_ActorInternal|CollisionType_ActorExternal); + if (body){ + if(actor) {dynamicsWorld->addRigidBody(body,CollisionType_ActorInternal,CollisionType_World|CollisionType_ActorInternal);std::cout << "actor";} + else dynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_ActorInternal|CollisionType_ActorExternal); + } if (raycastingBody) dynamicsWorld->addRigidBody(raycastingBody,CollisionType_Raycasting,CollisionType_Raycasting|CollisionType_World); @@ -603,14 +605,15 @@ namespace Physic { } - std::pair PhysicEngine::rayTest(btVector3& from,btVector3& to) + std::pair PhysicEngine::rayTest(btVector3& from,btVector3& to,bool raycastingObjectOnly) { std::string name = ""; float d = -1; float d1 = 10000.; btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to); - resultCallback1.m_collisionFilterMask = CollisionType_Raycasting; + if(raycastingObjectOnly) resultCallback1.m_collisionFilterMask = CollisionType_Raycasting; + else resultCallback1.m_collisionFilterMask = CollisionType_ActorExternal; dynamicsWorld->rayTest(from, to, resultCallback1); if (resultCallback1.hasHit()) { diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 67e94c8f8..063c8be0e 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -226,7 +226,7 @@ namespace Physic /** * Add a RigidBody to the simulation */ - void addRigidBody(RigidBody* body, bool addToMap = true, RigidBody* raycastingBody = NULL); + void addRigidBody(RigidBody* body, bool addToMap = true, RigidBody* raycastingBody = NULL,bool actor = false); /** * Remove a RigidBody from the simulation. It does not delete it, and does not remove it from the RigidBodyMap. @@ -293,7 +293,7 @@ namespace Physic /** * Return the closest object hit by a ray. If there are no objects, it will return ("",-1). */ - std::pair rayTest(btVector3& from,btVector3& to); + std::pair rayTest(btVector3& from,btVector3& to,bool raycastingObjectOnly = true); /** * Return all objects hit by a ray.