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)); }
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); }
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)); }
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); }
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; } }
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); }
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); }