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 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 List <Vector3> GetPreviousFreeFallBottomPositionsForRayCast(BoundBase characterBound, MovableEntity characterEntity)
        {
            Vector3 boundOrigin = characterBound.GetOrigin();
            Vector3 boundMax    = characterBound.GetMax();
            Vector3 boundMin    = characterBound.GetMin();

            Vector3 velocityToPreviousPosition = BodyMechanics.GetFreeFallVelocity(characterEntity.Velocity);

            boundMax    -= velocityToPreviousPosition;
            boundMin    -= velocityToPreviousPosition;
            boundOrigin -= velocityToPreviousPosition;


            FRay[] rays = new FRay[9]
            {
                new FRay(new Vector3(boundMax.X, boundMax.Y, boundMax.Z), characterEntity.Velocity),
                new FRay(new Vector3(boundMax.X, boundMax.Y, boundMin.Z), characterEntity.Velocity),
                new FRay(new Vector3(boundMax.X, boundMin.Y, boundMax.Z), characterEntity.Velocity),
                new FRay(new Vector3(boundMax.X, boundMin.Y, boundMin.Z), characterEntity.Velocity),
                new FRay(new Vector3(boundMin.X, boundMax.Y, boundMax.Z), characterEntity.Velocity),
                new FRay(new Vector3(boundMin.X, boundMax.Y, boundMin.Z), characterEntity.Velocity),
                new FRay(new Vector3(boundMin.X, boundMin.Y, boundMax.Z), characterEntity.Velocity),
                new FRay(new Vector3(boundMin.X, boundMin.Y, boundMin.Z), characterEntity.Velocity),
                new FRay(boundOrigin, characterEntity.Velocity)
            };

            return(GetRayCastPositionsOnCharacterBoundByVelocity(rays, characterBound, boundMax, boundMin, boundOrigin));
        }
        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;
            }
            }
        }