コード例 #1
0
        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();
        }
コード例 #2
0
        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();
        }
コード例 #3
0
        private void InterProcessDownRayCastCollision(MovableEntity character, BoundBase characterBound, List <BoundBase> collidedBounds)
        {
            List <Vector3> currentPositionsForRayCast = GetCurrentMiddlePositionsForRayCast(characterBound, character);
            List <FRay>    listOfRays = new List <FRay>();

            for (Int32 i = 0; i < currentPositionsForRayCast.Count; i++)
            {
                listOfRays.Add(new FRay(currentPositionsForRayCast[i], -GameWorld.GetWorldInstance().GetLevel().Camera.GetLocalSpaceUpVector()));
            }

            RayCastOutputData closestRayCastDown = GetClosestRayCastResultFromMultipleRayCast(listOfRays, collidedBounds, character);

            if (RAYCAST_COLLIDED(closestRayCastDown.shortestDistance))
            {
                // Character could be elevated on collided mesh

                if (closestRayCastDown.shortestDistance <= (characterBound.GetExtent().Y * 2))
                {
                    float   distanceToStep    = (characterBound.GetExtent().Y - closestRayCastDown.shortestDistance);
                    Vector3 elevationPosition = characterBound.GetOrigin();
                    elevationPosition.Y += distanceToStep;
                    character.SetPosition(elevationPosition);
                    character.ActorState = BehaviorState.IDLE;
                }
                // Character now goes to free fall
                else
                {
                    character.ActorState = BehaviorState.FREE_FALLING;
                }

                character.pushPosition();
            }
            else
            {
                character.popPosition();
                character.ActorState = BehaviorState.IDLE;
            }
        }
コード例 #4
0
        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;
            }
            }
        }
コード例 #5
0
        private void ProcessCollisionAtState_Move(MovableEntity characterEntity, Entity collidedEntity, List <BoundBase> collidedBounds)
        {
            switch (GetEntityType(collidedEntity))
            {
            // If character collided character during move
            case EntityType.MOVABLE_ENTITY:
            {
                characterEntity.popPosition();
                characterEntity.ActorState = BehaviorState.IDLE;
                break;
            }

            case EntityType.STATIC_ENTITY:
            {
                BoundBase characterBound = characterEntity.GetCharacterCollisionBound();

                // 1) First of all character has to do ray cast in move direction
                List <Vector3> previousPositionsForRayCast = GetPreviousClosestPositionsForRayCast(characterBound, characterEntity.Speed, characterEntity);
                List <FRay>    listOfRays = new List <FRay>();
                for (Int32 i = 0; i < previousPositionsForRayCast.Count; i++)
                {
                    listOfRays.Add(new FRay(previousPositionsForRayCast[i], characterEntity.Velocity));
                }
                RayCastOutputData outputData = GetClosestRayCastResultFromMultipleRayCastExt(listOfRays, collidedBounds, characterEntity);

                // Ray intersected with one of collided bounds
                if (RAYCAST_COLLIDED(outputData.shortestDistance))
                {
                    // Distance to collided bound is too large and character can't step so far
                    // In this case do ray cast down from current character position
                    if (RAYCAST_INTERSECTION_FAR((characterEntity.Velocity * characterEntity.Speed).Length, outputData.shortestDistance))
                    {
                        InterProcessDownRayCastCollision(characterEntity, characterBound, collidedBounds);
                    }
                    // Distance to collided bound is small enough to step there
                    // In this case acquire normal to that plane to find out can character step on that surface, if no - pop previous position and set to idle
                    else
                    {
                        var rayCastResults = GetRayCastResultsFromMultipleRayCast(listOfRays, collidedBounds, characterEntity);
                        var upperRayResult = GetClosestAndHighestRay(rayCastResults, characterBound);

                        bool bCanElevateOnMesh = true;

                        if (upperRayResult != null)
                        {
                            // check normal of collided plane
                            BoundBase bound = outputData.collidedBound;
                            Vector3   normalToCollidedPlane = bound.GetNormalToIntersectedPosition(outputData.intersectionPosition);
                            if (!REACHABLE_INCLINE(normalToCollidedPlane))
                            {
                                bCanElevateOnMesh = false;
                            }
                        }

                        if (bCanElevateOnMesh)
                        {
                            Vector3 NewCharacterPosition = characterBound.GetOrigin();
                            NewCharacterPosition.Y = outputData.intersectionPosition.Y + characterBound.GetExtent().Y;
                            characterEntity.SetPosition(NewCharacterPosition);
                            characterEntity.pushPosition();
                        }
                        else
                        {
                            characterEntity.popPosition();
                        }

                        characterEntity.ActorState = BehaviorState.IDLE;
                    }
                }

                /*  There was no intersection with ray, this could be one of these reasons :
                 *   Probably case :
                 *   1) Character is on terrain;
                 *   2) Character is in free falling.
                 */
                else
                {
                    InterProcessDownRayCastCollision(characterEntity, characterBound, collidedBounds);
                }
                break;
            }
            }
        }