mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-10-31 16:56:47 +00:00 
			
		
		
		
	Use sphere cast instead of ray for camera distance adjustment; use the box orientation value in newtrace
This commit is contained in:
		
							parent
							
								
									61e476118d
								
							
						
					
					
						commit
						91c89e5db4
					
				
					 7 changed files with 60 additions and 28 deletions
				
			
		|  | @ -322,10 +322,9 @@ void RenderingManager::update (float duration, bool paused) | |||
| 
 | ||||
|         btVector3 btOrig(orig.x, orig.y, orig.z); | ||||
|         btVector3 btDest(dest.x, dest.y, dest.z); | ||||
|         std::pair<std::string,float> test = mPhysicsEngine->rayTest(btOrig, btDest); | ||||
|         if (!test.first.empty()) { | ||||
|         std::pair<bool, float> test = mPhysicsEngine->sphereCast(mRendering.getCamera()->getNearClipDistance()*2.5, btOrig, btDest); | ||||
|         if (test.first) | ||||
|             mCamera->setCameraDistance(test.second * orig.distance(dest), false, false); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     mOcclusionQuery->update(duration); | ||||
|  |  | |||
|  | @ -33,23 +33,23 @@ namespace MWWorld | |||
|     class MovementSolver | ||||
|     { | ||||
|     private: | ||||
|         static bool stepMove(Ogre::Vector3& position, const Ogre::Vector3 &velocity, float remainingTime, | ||||
|         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
 | ||||
| 
 | ||||
|             newtrace(&trace, position, position+Ogre::Vector3(0.0f,0.0f,sStepSize), | ||||
|             newtrace(&trace, orient, position, position+Ogre::Vector3(0.0f,0.0f,sStepSize), | ||||
|                      halfExtents, isInterior, engine); | ||||
|             if(trace.fraction == 0.0f) | ||||
|                 return false; | ||||
| 
 | ||||
|             newtrace(&trace, trace.endpos, trace.endpos + velocity*remainingTime, | ||||
|             newtrace(&trace, orient, trace.endpos, trace.endpos + velocity*remainingTime, | ||||
|                      halfExtents, isInterior, engine); | ||||
|             if(trace.fraction == 0.0f || (trace.fraction != 1.0f && getSlope(trace.planenormal) > sMaxSlope)) | ||||
|                 return false; | ||||
| 
 | ||||
|             newtrace(&trace, trace.endpos, trace.endpos-Ogre::Vector3(0.0f,0.0f,sStepSize), halfExtents, isInterior, engine); | ||||
|             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.
 | ||||
|  | @ -111,15 +111,9 @@ namespace MWWorld | |||
|             traceResults trace; //no initialization needed
 | ||||
| 
 | ||||
|             int maxHeight = 400.f; | ||||
|             int steps = 100; | ||||
|             for (int i=0; i<steps; ++i) | ||||
|             { | ||||
|                 newtrace(&trace, newPosition, newPosition-Ogre::Vector3(0,0,maxHeight / steps), halfExtents, isInterior, engine); | ||||
|                 if(trace.fraction < 1.0f) | ||||
|                     hit = true; | ||||
|                 newPosition = trace.endpos; | ||||
|             } | ||||
| 
 | ||||
|             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); | ||||
|  | @ -154,7 +148,7 @@ namespace MWWorld | |||
|             bool isInterior = !ptr.getCell()->isExterior(); | ||||
|             Ogre::Vector3 halfExtents = physicActor->getHalfExtents();// + Vector3(1,1,1);
 | ||||
|             physicActor->enableCollisions(false); | ||||
| 
 | ||||
|             Ogre::Quaternion orient = Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::UNIT_Z); | ||||
|             Ogre::Vector3 velocity; | ||||
|             if(!gravity) | ||||
|             { | ||||
|  | @ -167,7 +161,7 @@ namespace MWWorld | |||
|             { | ||||
|                 if(!(movement.z > 0.0f)) | ||||
|                 { | ||||
|                     newtrace(&trace, position, position-Ogre::Vector3(0,0,4), halfExtents, isInterior, engine); | ||||
|                     newtrace(&trace, orient, position, position-Ogre::Vector3(0,0,4), halfExtents, isInterior, engine); | ||||
|                     if(trace.fraction < 1.0f && getSlope(trace.planenormal) <= sMaxSlope) | ||||
|                         onground = true; | ||||
|                 } | ||||
|  | @ -188,7 +182,7 @@ namespace MWWorld | |||
|             int iterations = 0; | ||||
|             do { | ||||
|                 // trace to where character would go if there were no obstructions
 | ||||
|                 newtrace(&trace, newPosition, newPosition+clippedVelocity*remainingTime, halfExtents, isInterior, engine); | ||||
|                 newtrace(&trace, orient, newPosition, newPosition+clippedVelocity*remainingTime, halfExtents, isInterior, engine); | ||||
|                 newPosition = trace.endpos; | ||||
|                 remainingTime = remainingTime * (1.0f-trace.fraction); | ||||
| 
 | ||||
|  | @ -207,7 +201,7 @@ namespace MWWorld | |||
|                     { | ||||
|                         // Can't walk on this. Try to step up onto it.
 | ||||
|                         if((gravity && !onground) || | ||||
|                            !stepMove(newPosition, velocity, remainingTime, halfExtents, isInterior, engine)) | ||||
|                            !stepMove(newPosition, orient, velocity, remainingTime, halfExtents, isInterior, engine)) | ||||
|                         { | ||||
|                             Ogre::Vector3 resultantDirection = trace.planenormal.crossProduct(up); | ||||
|                             resultantDirection.normalise(); | ||||
|  | @ -225,7 +219,7 @@ namespace MWWorld | |||
| 
 | ||||
|             if(onground) | ||||
|             { | ||||
|                 newtrace(&trace, newPosition, newPosition-Ogre::Vector3(0,0,sStepSize+4.0f), halfExtents, isInterior, engine); | ||||
|                 newtrace(&trace, orient, newPosition, newPosition-Ogre::Vector3(0,0,sStepSize+4.0f), halfExtents, isInterior, engine); | ||||
|                 if(trace.fraction < 1.0f && getSlope(trace.planenormal) <= sMaxSlope) | ||||
|                     newPosition.z = trace.endpos.z + 2.0f; | ||||
|                 else | ||||
|  |  | |||
|  | @ -973,6 +973,8 @@ namespace MWWorld | |||
|         if(duration <= 0.0f) | ||||
|             return; | ||||
| 
 | ||||
|         processDoors(duration); | ||||
| 
 | ||||
|         PtrMovementList::const_iterator player(actors.end()); | ||||
|         for(PtrMovementList::const_iterator iter(actors.begin());iter != actors.end();iter++) | ||||
|         { | ||||
|  | @ -998,8 +1000,6 @@ namespace MWWorld | |||
|             moveObjectImp(player->first, vec.x, vec.y, vec.z); | ||||
|         } | ||||
| 
 | ||||
|         processDoors(duration); | ||||
| 
 | ||||
|         mPhysEngine->stepSimulation (duration); | ||||
|     } | ||||
| 
 | ||||
|  | @ -1022,6 +1022,7 @@ namespace MWWorld | |||
|                 mPhysics->getObjectAABB(it->first, min, max); | ||||
|                 Ogre::Vector3 dimensions = max-min; | ||||
| 
 | ||||
|                 /// \todo should use convexSweepTest here
 | ||||
|                 std::vector<std::string> collisions = mPhysics->getCollisions(it->first); | ||||
|                 for (std::vector<std::string>::iterator cit = collisions.begin(); cit != collisions.end(); ++cit) | ||||
|                 { | ||||
|  |  | |||
|  | @ -622,6 +622,41 @@ namespace Physic | |||
|         return std::pair<std::string,float>(name,d); | ||||
|     } | ||||
| 
 | ||||
|     // callback that ignores player in results
 | ||||
|     struct	OurClosestConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback | ||||
|     { | ||||
|     public: | ||||
|         OurClosestConvexResultCallback(const btVector3&	convexFromWorld,const btVector3&	convexToWorld) | ||||
|             : btCollisionWorld::ClosestConvexResultCallback(convexFromWorld, convexToWorld) {} | ||||
| 
 | ||||
|         virtual	btScalar	addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace) | ||||
|         { | ||||
|             if (const RigidBody* body = dynamic_cast<const RigidBody*>(convexResult.m_hitCollisionObject)) | ||||
|                 if (body->mName == "player") | ||||
|                     return 0; | ||||
|             return btCollisionWorld::ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     std::pair<bool, float> PhysicEngine::sphereCast (float radius, btVector3& from, btVector3& to) | ||||
|     { | ||||
|         OurClosestConvexResultCallback callback(from, to); | ||||
|         callback.m_collisionFilterMask = OEngine::Physic::CollisionType_World; | ||||
| 
 | ||||
|         btSphereShape shape(radius); | ||||
|         const btQuaternion btrot(0.0f, 0.0f, 0.0f); | ||||
| 
 | ||||
|         btTransform from_ (btrot, from); | ||||
|         btTransform to_ (btrot, to); | ||||
| 
 | ||||
|         dynamicsWorld->convexSweepTest(&shape, from_, to_, callback); | ||||
| 
 | ||||
|         if (callback.hasHit()) | ||||
|             return std::make_pair(true, callback.m_closestHitFraction); | ||||
|         else | ||||
|             return std::make_pair(false, 1); | ||||
|     } | ||||
| 
 | ||||
|     std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(btVector3& from, btVector3& to) | ||||
|     { | ||||
|         MyRayResultCallback resultCallback1; | ||||
|  |  | |||
|  | @ -298,6 +298,9 @@ namespace Physic | |||
|          */ | ||||
|         std::vector< std::pair<float, std::string> > rayTest2(btVector3& from, btVector3& to); | ||||
| 
 | ||||
|         std::pair<bool, float> sphereCast (float radius, btVector3& from, btVector3& to); | ||||
|         ///< @return (hit, relative distance)
 | ||||
| 
 | ||||
|         std::vector<std::string> getCollisions(const std::string& name); | ||||
| 
 | ||||
|         //event list of non player object
 | ||||
|  |  | |||
|  | @ -15,16 +15,16 @@ enum traceWorldType | |||
|     bothWorldTrace = collisionWorldTrace | pickWorldTrace | ||||
| }; | ||||
| 
 | ||||
| void newtrace(traceResults *results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, bool isInterior, OEngine::Physic::PhysicEngine *enginePass)  //Traceobj was a Aedra Object
 | ||||
| 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 btrot(0.0f, 0.0f, 0.0f);   //y, x, 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(btrot, btstart); | ||||
|     const btTransform to(btrot, btend); | ||||
|     const btTransform from(btorient, btstart); | ||||
|     const btTransform to(btorient, btend); | ||||
| 
 | ||||
|     btCollisionWorld::ClosestConvexResultCallback newTraceCallback(btstart, btend); | ||||
|     newTraceCallback.m_collisionFilterMask = OEngine::Physic::CollisionType_World; | ||||
|  |  | |||
|  | @ -21,6 +21,6 @@ struct traceResults | |||
|     float fraction; | ||||
| }; | ||||
| 
 | ||||
| void newtrace(traceResults *results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, bool isInterior, OEngine::Physic::PhysicEngine* enginePass); | ||||
| 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); | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue