public RayCastOutputData(FRay ray, BoundBase boundBase, float shortestDistance, Vector3 intersectionPosition)
 {
     parentRay                 = ray;
     collidedBound             = boundBase;
     this.shortestDistance     = shortestDistance;
     this.intersectionPosition = intersectionPosition;
 }
        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 List <Vector3> GetPreviousClosestPositionsForRayCast(BoundBase characterBound, float timeInterval, MovableEntity characterEntity)
        {
            Vector3 velocityToPreviousPosition = characterEntity.Velocity * (-timeInterval);

            Vector3 boundOrigin = characterBound.GetOrigin();
            Vector3 boundMax    = characterBound.GetMax();
            Vector3 boundMin    = characterBound.GetMin();

            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 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));
        }
Esempio n. 5
0
        public static bool GetIsBoundInFrustum(BoundBase boundingBox, ref Matrix4 viewMatrix, ref Matrix4 projectionMatrix)
        {
            bool bInFrustum = false;

            Matrix4 viewprojectionMatrix = Matrix4.Mult(viewMatrix, projectionMatrix);

            Vector3[] bbVertices = boundingBox.GetWorldSpaceVertices();

            for (Int32 i = 0; i < bbVertices.Length; i++)
            {
                // Transform to clipped space
                Vector4 clippedSpace = Vector4.Transform(new Vector4(bbVertices[i], 1.0f), viewprojectionMatrix);
                // Transform to normalized device coordinates
                Vector3 ndc = clippedSpace.Xyz / clippedSpace.W;

                if (ndc.X >= -1 && ndc.X <= 1 &&
                    ndc.Y >= -1 && ndc.Y <= 1 &&
                    ndc.Z >= -1 && ndc.Z <= 1)
                {
                    bInFrustum = true;
                    break;
                }
            }

            return(bInFrustum);
        }
        private BoundBase UpdateBound()
        {
            BoundBase resultBound = null;

            if (bComponentHierarchyChangedDirty || bTransformationDirty)
            {
                AABB aabb = AABB.CreateFromMinMax(FindEdgeInMesh((lhv, rhv) => { return(Math.Min(lhv, rhv)); }),
                                                  FindEdgeInMesh((lhv, rhv) => { return(Math.Max(lhv, rhv)); }), this);
                Matrix4    TransformMatrix = GetWorldMatrix();
                Quaternion rotation        = TransformMatrix.ExtractRotation();
                if (rotation.Xyz.LengthSquared > 0.01f)
                {
                    resultBound = new OBB(aabb.GetLocalSpaceOrigin(), aabb.GetLocalSpaceExtent(), TransformMatrix, this);
                }
                else
                {
                    aabb.ScalePlusTranslation = TransformMatrix;
                    resultBound = aabb;
                }
                bComponentHierarchyChangedDirty = false;
            }
            else
            {
                resultBound = Bound;
            }
            return(resultBound);
        }
Esempio n. 7
0
 public virtual void IsLitByLightSource(List <PointLight> LightList)
 {
     m_lightVisibilityMap.Init(LightList.Count, false);
     for (Int32 i = 0; i < LightList.Count; i++)
     {
         BoundBase bound       = GetAABBFromAllChildComponents();
         FSphere   boundSphere = (FSphere)bound;
         FSphere   lightSphere = new FSphere(LightList[i].Position.Xyz, LightList[i].AttenuationRadius);
         m_lightVisibilityMap[i] = GeometryMath.IsSphereVsSphereIntersection(ref boundSphere, ref lightSphere);
     }
 }
        private BoundBase CreateBound()
        {
            BoundBase  resultBound     = null;
            AABB       aabb            = AABB.CreateFromMinMax(FindMinFromModel(), FindMaxFromModel(), this);
            Matrix4    TransformMatrix = GetWorldMatrix();
            Quaternion rotation        = TransformMatrix.ExtractRotation();

            if (rotation.Xyz.LengthSquared > 0.01f)
            {
                resultBound = new OBB(aabb.GetLocalSpaceOrigin(), aabb.GetLocalSpaceExtent(), TransformMatrix, this);
            }
            else
            {
                aabb.ScalePlusTranslation = TransformMatrix;
                resultBound = aabb;
            }
            return(resultBound);
        }
        private List <Vector3> GetCurrentMiddlePositionsForRayCast(BoundBase characterBound, MovableEntity characterEntity)
        {
            Vector3 boundOrigin = characterBound.GetOrigin();
            Vector3 boundMax    = characterBound.GetMax();
            Vector3 boundMin    = characterBound.GetMin();

            Vector3 tangentY = -characterBound.GetTangetY();

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

            return(GetClosestPositionsForRayCast(rays, characterBound, boundMax, boundMin, boundOrigin, boundOrigin.Y));
        }
Esempio n. 10
0
        private bool BoundBaseCollision_Ext(BoundBase characterBound, BoundBase collidedRootBound)
        {
            bool bHasCollision = false;

            BoundBase.BoundType collisionType = characterBound.GetBoundType() | collidedRootBound.GetBoundType();

            if (collisionType == (BoundBase.BoundType.AABB | BoundBase.BoundType.OBB))
            {
                AABB aabb = characterBound.GetBoundType() == BoundBase.BoundType.AABB ? characterBound as AABB : collidedRootBound as AABB;
                OBB  obb  = collidedRootBound.GetBoundType() == BoundBase.BoundType.OBB ? collidedRootBound as OBB : characterBound as OBB;
                bHasCollision = GeometryMath.AABBOBB(aabb, obb);
            }
            else if (collisionType == (BoundBase.BoundType.AABB | BoundBase.BoundType.AABB))
            {
                bHasCollision = GeometryMath.AABBAABB(characterBound as AABB, collidedRootBound as AABB);
            }
            else
            {
                bHasCollision = GeometryMath.OBBOBB(characterBound as OBB, collidedRootBound as OBB);
            }
            return(bHasCollision);
        }
Esempio n. 11
0
        public void TryEntityCollision(Component characterRootComponent)
        {
            CollisionUnit    characterCollisionUnit = CollisionUnits.Find(unit => unit.RootComponent == characterRootComponent);
            Component        collidedRootComponent = null;
            BoundBase        characterBound = characterCollisionUnit.GetFirstBoundingBox();
            List <BoundBase> collidedRootBounds = new List <BoundBase>();
            bool             bFrameBoundingBoxCollision = false, bRegularBoundingBoxCollision = false;

            // Check Collision. Step 1  - check axis aligned framing bounding boxes for collision -- (PRE COLLISION)
            CheckFrameBoundingBoxCollision(ref bFrameBoundingBoxCollision, ref characterRootComponent, ref characterCollisionUnit, ref collidedRootComponent, ref collidedRootBounds);

            // Check Collision. Step 2 - check all bounding boxes of concrete component for collision -- (PURE COLLISION DETECTION)
            List <BoundBase> collidedBounds = new List <BoundBase>();

            CheckRegularBoundingBoxCollision(ref bRegularBoundingBoxCollision, ref characterRootComponent, ref collidedRootComponent, ref collidedRootBounds, ref characterBound, ref collidedBounds);

            // Check Collision. Step 3 - Ray trace -- (BEHAVIOR OF COLLISION RESOLVING)
            BehaviorManager.ProcessCollision(CollisionOutput);

            // Clear all output after collision handling
            CollisionOutput.Clear();
        }
        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;
            }
        }
Esempio n. 13
0
        private static BoundBase UpdateCollisionBound(ref SceneComponent component, float[,] vertices)
        {
            BoundBase resultBound = null;

            AABB aabb = AABB.CreateFromMinMax(
                FindEdgeInMesh((lhv, rhv) => { return(Math.Min(lhv, rhv)); }, vertices),
                FindEdgeInMesh((lhv, rhv) => { return(Math.Max(lhv, rhv)); }, vertices),
                component);
            Matrix4    TransformMatrix = component.GetWorldMatrix();
            Quaternion rotation        = TransformMatrix.ExtractRotation();

            if (rotation.Xyz.LengthSquared > 0.01f)
            {
                resultBound = new OBB(aabb.GetLocalSpaceOrigin(), aabb.GetLocalSpaceExtent(), TransformMatrix, component);
            }
            else
            {
                aabb.ScalePlusTranslation = TransformMatrix;
                resultBound = aabb;
            }

            return(resultBound);
        }
        private List <Vector3> GetClosestPositionsForRayCast(FRay[] insideCastRays, BoundBase characterBound, Vector3 boundMax, Vector3 boundMin, Vector3 boundOrigin, float ResultHeight)
        {
            List <Vector3> rayCastPositions = new List <Vector3>();

            for (Int32 i = 0; i < insideCastRays.Length; i++)
            {
                FRay  ray = insideCastRays[i];
                float localIntersectionDistance = 0.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());
                }

                Vector3 intersectionPosition = ray.GetPositionInTime(localIntersectionDistance);
                rayCastPositions.Add(new Vector3(intersectionPosition.X, ResultHeight, intersectionPosition.Z));
            }
            return(rayCastPositions);
        }
Esempio n. 15
0
        private void CheckRegularBoundingBoxCollision(ref bool bRegularBoundingBoxCollision, ref Component characterRootComponent, ref Component collidedRootComponent,
                                                      ref List <BoundBase> collidedRootBounds, ref BoundBase characterBound, ref List <BoundBase> collidedBounds)
        {
            foreach (var testingBound in collidedRootBounds)
            {
                if (BoundBaseCollision_Ext(characterBound, testingBound))
                {
                    collidedBounds.Add(testingBound);
                }
            }

            if (collidedBounds.Count > 0)
            {
                bRegularBoundingBoxCollision = true;
            }

            if (bRegularBoundingBoxCollision)
            {
                CollisionOutput.Add(new CollisionOutputRegularOBB(characterRootComponent, collidedRootComponent, collidedBounds));
            }
        }
        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;
            }
            }
        }
        private RayCastOutputData GetClosestAndHighestRay(List <RayCastOutputData> rayCastResults, BoundBase characterBound)
        {
            float             boundMaxY         = characterBound.GetMax().Y;
            RayCastOutputData rayCastOutputData = null;

            List <RayCastOutputData> mostHighRayCastPositionResults = new List <RayCastOutputData>();

            // find rays with the most high start position
            foreach (var result in rayCastResults)
            {
                if (result.shortestDistance > -1 && GeometryMath.CMP(result.parentRay.StartPosition.Y, boundMaxY) > 0)
                {
                    mostHighRayCastPositionResults.Add(result);
                }
            }

            if (mostHighRayCastPositionResults.Count > 1)
            {
                // find ray with the most close intersection position
                float intersectionDistance = mostHighRayCastPositionResults.First().shortestDistance;
                rayCastOutputData = mostHighRayCastPositionResults.First();

                for (Int32 i = 1; i < mostHighRayCastPositionResults.Count; i++)
                {
                    if (mostHighRayCastPositionResults[i].shortestDistance <= intersectionDistance)
                    {
                        rayCastOutputData    = mostHighRayCastPositionResults[i];
                        intersectionDistance = rayCastOutputData.shortestDistance;
                    }
                }
            }

            return(rayCastOutputData);
        }