private void ProcessNoCollisionAtState_Move(MovableEntity character) { Vector3 boundMin = character.GetCharacterCollisionBound().GetMin(); Vector3 origin = character.GetCharacterCollisionBound().GetOrigin(); // Ray cast from middle height position to avoid miss ray casting Vector3 rayCastStartPosition = new Vector3(origin); FRay rayDown = new FRay(rayCastStartPosition, -GameWorld.GetWorldInstance().GetLevel().Camera.GetLocalSpaceUpVector()); float intersectionDistance = LandscapeRayIntersection.Intersection_TerrainRay(GameWorld.GetWorldInstance().GetLevel().Terrain.GetData(), rayDown); // Subtract length of bound extent from middle height position float boundExtent = origin.Y - boundMin.Y; float actualIntersectionDistance = intersectionDistance - boundExtent; // Character is in free fall, next position will be calculated in next tick if (intersectionDistance < 0.0f || RAYCAST_INTERSECTION_FAR(BodyMechanics.GetFreeFallDistanceInVelocity(character.Velocity), actualIntersectionDistance)) { character.ActorState = BehaviorState.FREE_FALLING; } // Check if character can reach that height else { // Character could be elevated on terrain Vector3 CharacterNewPosition = rayDown.GetPositionInTime(intersectionDistance); CharacterNewPosition.Y += character.GetCharacterCollisionBound().GetExtent().Y; character.SetPosition(CharacterNewPosition); character.ActorState = BehaviorState.IDLE; } // Push current position to stack character.pushPosition(); }
private void ProcessNoCollisionAtState_FreeFalling(MovableEntity character) { if (character.Velocity.LengthSquared > 0) { Vector3 boundMin = character.GetCharacterCollisionBound().GetMin(); // Raycast from bottom height point Vector3 rayCastStartPosition = new Vector3(character.GetCharacterCollisionBound().GetOrigin()); rayCastStartPosition.Y = boundMin.Y; FRay ray = new FRay(rayCastStartPosition, character.Velocity); float intersectionDistance = LandscapeRayIntersection.Intersection_TerrainRay(GameWorld.GetWorldInstance().GetLevel().Terrain.GetData(), ray); // Character is still in free fall, just update position if (intersectionDistance < 0.0f || RAYCAST_INTERSECTION_FAR(BodyMechanics.GetFreeFallDistanceInVelocity(character.Velocity), intersectionDistance)) { character.SetPosition(BodyMechanics.UpdateFreeFallPosition(character.ComponentTranslation, character.Velocity)); } // Character could be elevated on terrain else { Vector3 CharacterNewPosition = ray.GetPositionInTime(intersectionDistance); CharacterNewPosition.Y += character.GetCharacterCollisionBound().GetExtent().Y; character.SetPosition(CharacterNewPosition); character.ActorState = BehaviorState.IDLE; } } character.pushPosition(); }
private List <Vector3> GetRayCastPositionsOnCharacterBoundByVelocity(FRay[] insideCastRays, BoundBase characterBound, Vector3 boundMax, Vector3 boundMin, Vector3 boundOrigin) { List <Vector3> rayCastPositions = new List <Vector3>(); for (Int32 i = 0; i < insideCastRays.Length; i++) { FRay ray = insideCastRays[i]; float localIntersectionDistance = -1.0f; BoundBase.BoundType boundType = characterBound.GetBoundType(); if ((boundType & BoundBase.BoundType.AABB) == BoundBase.BoundType.AABB) { localIntersectionDistance = GeometryMath.Intersection_RayAABBExt(ray, boundMax, boundMin); } else if ((boundType & BoundBase.BoundType.OBB) == BoundBase.BoundType.OBB) { localIntersectionDistance = GeometryMath.Intersection_RayOBBExt(ray, (characterBound as OBB).GetTangetX(), (characterBound as OBB).GetTangetY(), (characterBound as OBB).GetTangetZ(), boundOrigin, (characterBound as OBB).GetExtent()); } if (localIntersectionDistance > -1.0f) { Vector3 intersectionPosition = ray.GetPositionInTime(localIntersectionDistance); rayCastPositions.Add(new Vector3(intersectionPosition)); } } return(rayCastPositions); }
private RayCastOutputData GetClosestRayCastResult(FRay ray, List <BoundBase> collidedBounds) { float resultShortestDistance = -1.0f; BoundBase resultBound = null; // DO RAY CAST IN ALL COLLIDED BOUNDING BOXES for (Int32 i = 0; i < collidedBounds.Count; i++) { float localIntersectionDistance = 0.0f; BoundBase.BoundType boundType = collidedBounds[i].GetBoundType(); if ((boundType & BoundBase.BoundType.AABB) == BoundBase.BoundType.AABB) { localIntersectionDistance = GeometryMath.Intersection_RayAABB(ray, collidedBounds[i] as AABB); } else if ((boundType & BoundBase.BoundType.OBB) == BoundBase.BoundType.OBB) { localIntersectionDistance = GeometryMath.Intersection_RayOBB(ray, collidedBounds[i] as OBB); } if (resultShortestDistance <= -1.0f || (localIntersectionDistance > 0.0f && localIntersectionDistance < resultShortestDistance)) { resultShortestDistance = localIntersectionDistance; resultBound = collidedBounds[i]; } } Vector3 intersectionPosition = ray.GetPositionInTime(resultShortestDistance); return(new RayCastOutputData(ray, resultBound, resultShortestDistance, intersectionPosition)); }
private static Vector3 getEndPoint(FRay ray) { return(ray.GetPositionInTime(RAY_DISTANCE)); }
private void ProcessCollisionAtState_FreeFalling(MovableEntity character, Entity collidedEntity, List <BoundBase> collidedBounds) { switch (GetEntityType(collidedEntity)) { // If character collided another character during free fall because of forward velocity case EntityType.MOVABLE_ENTITY: { // Restore previous position and set velocity to fall character.popPosition(); character.Velocity = -GameWorld.GetWorldInstance().GetLevel().Camera.GetLocalSpaceUpVector(); break; } // If character is in free falling but has encountered some collisions with bounds case EntityType.STATIC_ENTITY: { List <Vector3> previousRayCastPositions = GetPreviousFreeFallBottomPositionsForRayCast(character.GetCharacterCollisionBound(), character); List <FRay> listOfRays = new List <FRay>(); for (Int32 i = 0; i < previousRayCastPositions.Count; i++) { listOfRays.Add(new FRay(previousRayCastPositions[i], character.Velocity)); } FRay rayFromMiddleBottom = listOfRays.First(); // Necessary data for subsequent calculations RayCastOutputData rayCastOutputData = null; float terrainIntersectionDistance = LandscapeRayIntersection.Intersection_TerrainRay(GameWorld.GetWorldInstance().GetLevel().Terrain.GetData(), rayFromMiddleBottom); bool bTerrainIntersection = !(terrainIntersectionDistance < 0.0f || RAYCAST_INTERSECTION_FAR(BodyMechanics.GetFreeFallDistanceInVelocity(character.Velocity), terrainIntersectionDistance)); // No terrain intersection - check intersection with bounds if (!bTerrainIntersection) { rayCastOutputData = GetClosestRayCastResultFromMultipleRayCast(listOfRays, collidedBounds, character); // Ray collided with one of the bounds, check angle of that plane, if can elevate on it - do it if (RAYCAST_COLLIDED(rayCastOutputData.shortestDistance)) { Vector3 normalToCollidedPlane = rayCastOutputData.collidedBound.GetNormalToIntersectedPosition(rayCastOutputData.intersectionPosition); // Character can step on this surface if (REACHABLE_INCLINE(normalToCollidedPlane)) { Vector3 BoundOrigin = character.GetCharacterCollisionBound().GetOrigin(); Vector3 NewCharacterPosition = new Vector3(BoundOrigin.X, rayCastOutputData.intersectionPosition.Y + character.GetCharacterCollisionBound().GetExtent().Y, BoundOrigin.Z); character.SetPosition(NewCharacterPosition); character.pushPosition(); character.ActorState = BehaviorState.IDLE; } // If normal is down directed or too up directed - character can't step on this surface - return to previous position and set velocity to down else { // This is quick fix character.ActorState = BehaviorState.MOVE; character.popPosition(); character.Velocity = -GameWorld.GetWorldInstance().GetLevel().Camera.GetLocalSpaceUpVector(); } } // No ray collision, but bound collision exists, bound position is unknown - return to previous position and set velocity to down else { character.popPosition(); character.Velocity = -GameWorld.GetWorldInstance().GetLevel().Camera.GetLocalSpaceUpVector(); } } // Character could be elevated on terrain else { Vector3 CharacterNewPosition = rayFromMiddleBottom.GetPositionInTime(terrainIntersectionDistance); CharacterNewPosition.Y += character.GetCharacterCollisionBound().GetExtent().Y; character.SetPosition(CharacterNewPosition); character.ActorState = BehaviorState.IDLE; character.pushPosition(); } break; } } }