private bool CircleCastVertices( ref VoltRayCast bodySpaceRay, float radius, ref VoltRayResult result) { float sqrRadius = radius * radius; bool castHit = false; for (int i = 0; i < this.countBody; i++) { castHit |= Collision.CircleRayCast( this, this.bodyVertices[i], sqrRadius, ref bodySpaceRay, ref result); if (result.IsContained == true) { return(true); } } return(castHit); }
/// <summary> /// A cheap ray test that requires some precomputed information. /// Adapted from: http://www.cs.utah.edu/~awilliam/box/box.pdf /// </summary> private static bool RayCast( ref VoltRayCast ray, Fix64 top, Fix64 bottom, Fix64 left, Fix64 right) { Fix64 txmin = ((ray.signX ? right : left) - ray.origin.x) * ray.invDirection.x; Fix64 txmax = ((ray.signX ? left : right) - ray.origin.x) * ray.invDirection.x; Fix64 tymin = ((ray.signY ? top : bottom) - ray.origin.y) * ray.invDirection.y; Fix64 tymax = ((ray.signY ? bottom : top) - ray.origin.y) * ray.invDirection.y; if ((txmin > tymax) || (tymin > txmax)) { return(false); } if (tymin > txmin) { txmin = tymin; } if (tymax < txmax) { txmax = tymax; } return((txmax > Fix64.Zero) && (txmin < ray.distance)); }
public void CircleCast( ref VoltRayCast ray, float radius, VoltBuffer<VoltBody> outBuffer) { outBuffer.Add(this.bodies, this.count); }
/// <summary> /// Performs a circle cast on all world bodies. /// </summary> public bool CircleCast( ref VoltRayCast ray, Fix64 radius, ref VoltRayResult result, VoltBodyFilter filter = null, int ticksBehind = 0) { if (ticksBehind < 0) { throw new ArgumentOutOfRangeException("ticksBehind"); } this.reusableBuffer.Clear(); this.staticBroadphase.CircleCast(ref ray, radius, this.reusableBuffer); this.dynamicBroadphase.CircleCast(ref ray, radius, this.reusableBuffer); for (int i = 0; i < this.reusableBuffer.Count; i++) { VoltBody body = this.reusableBuffer[i]; if (VoltBody.Filter(body, filter)) { body.CircleCast(ref ray, radius, ref result, ticksBehind); if (result.IsContained) { return(true); } } } return(result.IsValid); }
internal VoltRayCast WorldToBodyRay(ref VoltRayCast rayCast) { return new VoltRayCast( this.WorldToBodyPoint(rayCast.origin), this.WorldToBodyDirection(rayCast.direction), rayCast.distance); }
public void CircleCast( ref VoltRayCast ray, float radius, VoltBuffer <VoltBody> outBuffer) { outBuffer.Add(this.bodies, this.count); }
void OnDrawGizmos() { VolatileWorld world = VolatileWorld.Instance; if ((world != null) && (Application.isPlaying == true)) { VoltRayResult result = new VoltRayResult(); VoltRayCast cast = new VoltRayCast( transform.position, transform.position + (transform.up * 100.0f)); if (this.radius > 0.0f) world.World.CircleCast(ref cast, this.radius, ref result, this.Filter, -this.frameOffset); else world.World.RayCast(ref cast, ref result, this.Filter, -this.frameOffset); float drawRadius = (this.radius == 0.0f) ? 0.2f : this.radius; Gizmos.color = this.color; if (result.IsValid == true) { Vector2 point = transform.position + (transform.up * result.Distance); Gizmos.DrawLine(transform.position, point); Gizmos.DrawWireSphere(point,drawRadius); } else { Gizmos.DrawLine(transform.position, transform.position + (transform.up * 100.0f)); } } }
/// <summary> /// A cheap ray test that requires some precomputed information. /// Adapted from: http://www.cs.utah.edu/~awilliam/box/box.pdf /// </summary> private static bool RayCast( ref VoltRayCast ray, float top, float bottom, float left, float right) { float txmin = ((ray.signX ? right : left) - ray.origin.x) * ray.invDirection.x; float txmax = ((ray.signX ? left : right) - ray.origin.x) * ray.invDirection.x; float tymin = ((ray.signY ? top : bottom) - ray.origin.y) * ray.invDirection.y; float tymax = ((ray.signY ? bottom : top) - ray.origin.y) * ray.invDirection.y; if ((txmin > tymax) || (tymin > txmax)) { return(false); } if (tymin > txmin) { txmin = tymin; } if (tymax < txmax) { txmax = tymax; } return((txmax > 0.0f) && (txmin < ray.distance)); }
internal VoltRayCast WorldToBodyRay(ref VoltRayCast rayCast) { return(new VoltRayCast( this.WorldToBodyPoint(rayCast.origin), this.WorldToBodyDirection(rayCast.direction), rayCast.distance)); }
/// <summary> /// Checks a ray against a circle with a given origin and square radius. /// </summary> internal static bool CircleRayCast( VoltShape shape, Vector2 shapeOrigin, float sqrRadius, ref VoltRayCast ray, ref VoltRayResult result) { Vector2 toOrigin = shapeOrigin - ray.origin; if (toOrigin.sqrMagnitude < sqrRadius) { result.SetContained(shape); return true; } float slope = Vector2.Dot(toOrigin, ray.direction); if (slope < 0) return false; float sqrSlope = slope * slope; float d = sqrRadius + sqrSlope - Vector2.Dot(toOrigin, toOrigin); if (d < 0) return false; float dist = slope - Mathf.Sqrt(d); if (dist < 0 || dist > ray.distance) return false; // N.B.: For historical raycasts this normal will be wrong! // Must be either transformed back to world or invalidated later. Vector2 normal = (dist * ray.direction - toOrigin).normalized; result.Set(shape, dist, normal); return true; }
private void ExplosionCallback( VoltRayCast rayCast, VoltRayResult rayResult, float rayWeight) { Vector2 point = rayResult.ComputePoint(ref rayCast); this.hits.Add(point); }
/// <summary> /// Note: This doesn't take rounded edges into account. /// </summary> public bool CircleCastApprox(ref VoltRayCast ray, float radius) { return(VoltAABB.RayCast( ref ray, this.top + radius, this.bottom - radius, this.left - radius, this.right + radius)); }
public bool RayCast(ref VoltRayCast ray) { return(VoltAABB.RayCast( ref ray, this.top, this.bottom, this.left, this.right)); }
protected override bool ShapeRayCast( ref VoltRayCast bodySpaceRay, ref VoltRayResult result) { return(Collision.CircleRayCast( this, this.bodySpaceOrigin, this.sqrRadius, ref bodySpaceRay, ref result)); }
/// <summary> /// Performs a raycast check on this shape. /// Begins with an AABB check. /// </summary> internal bool RayCast( ref VoltRayCast bodySpaceRay, ref VoltRayResult result) { // Queries and casts on shapes are always done in body space if (this.bodySpaceAABB.RayCast(ref bodySpaceRay)) { return(this.ShapeRayCast(ref bodySpaceRay, ref result)); } return(false); }
/// <summary> /// Performs a circlecast check on this shape. /// Begins with an AABB check. /// </summary> internal bool CircleCast( ref VoltRayCast bodySpaceRay, float radius, ref VoltRayResult result) { // Queries and casts on shapes are always done in body space if (this.bodySpaceAABB.CircleCastApprox(ref bodySpaceRay, radius)) { return(this.ShapeCircleCast(ref bodySpaceRay, radius, ref result)); } return(false); }
public void RayCast( ref VoltRayCast ray, VoltBuffer <VoltBody> outBuffer) { this.StartQuery(outBuffer); while (this.queryStack.Count > 0) { Node node = this.GetNextNode(); if (node.aabb.RayCast(ref ray)) { this.ExpandNode(node, outBuffer); } } }
protected override bool ShapeCircleCast( ref VoltRayCast bodySpaceRay, float radius, ref VoltRayResult result) { float totalRadius = this.radius + radius; return(Collision.CircleRayCast( this, this.bodySpaceOrigin, totalRadius * totalRadius, ref bodySpaceRay, ref result)); }
public void CircleCast( ref VoltRayCast ray, Fix64 radius, VoltBuffer <VoltBody> outBuffer) { this.StartQuery(outBuffer); while (this.queryStack.Count > 0) { Node node = this.GetNextNode(); if (node.aabb.CircleCastApprox(ref ray, radius)) { this.ExpandNode(node, outBuffer); } } }
public void PerformExplosion( TSVector2 origin, FP radius, VoltExplosionCallback callback, VoltBodyFilter targetFilter = null, VoltBodyFilter occlusionFilter = null, int ticksBehind = 0, int rayCount = 32) { if (ticksBehind < 0) { throw new ArgumentOutOfRangeException("ticksBehind"); } // Get all target bodies this.PopulateFiltered( origin, radius, targetFilter, ticksBehind, ref this.targetBodies); // Get all occluding bodies this.PopulateFiltered( origin, radius, occlusionFilter, ticksBehind, ref this.occludingBodies); VoltRayCast ray; FP rayWeight = 1.0f / rayCount; FP angleIncrement = (TSMath.Pi * 2.0f) * rayWeight; for (int i = 0; i < rayCount; i++) { TSVector2 normal = VoltMath.Polar(angleIncrement * i); ray = new VoltRayCast(origin, normal, radius); FP minDistance = this.GetOccludingDistance(ray, ticksBehind); minDistance += VoltWorld.EXPLOSION_OCCLUDER_SLOP; this.TestTargets(ray, callback, ticksBehind, minDistance, rayWeight); } }
/// <summary> /// Checks a ray against a circle with a given origin and square radius. /// </summary> internal static bool CircleRayCast( VoltShape shape, Vector2 shapeOrigin, float sqrRadius, ref VoltRayCast ray, ref VoltRayResult result) { Vector2 toOrigin = shapeOrigin - ray.origin; if (toOrigin.sqrMagnitude < sqrRadius) { result.SetContained(shape); return(true); } float slope = Vector2.Dot(toOrigin, ray.direction); if (slope < 0) { return(false); } float sqrSlope = slope * slope; float d = sqrRadius + sqrSlope - Vector2.Dot(toOrigin, toOrigin); if (d < 0) { return(false); } float dist = slope - Mathf.Sqrt(d); if (dist < 0 || dist > ray.distance) { return(false); } // N.B.: For historical raycasts this normal will be wrong! // Must be either transformed back to world or invalidated later. Vector2 normal = (dist * ray.direction - toOrigin).normalized; result.Set(shape, dist, normal); return(true); }
protected override bool ShapeCircleCast( ref VoltRayCast bodySpaceRay, float radius, ref VoltRayResult result) { bool checkVertices = this.CircleCastVertices( ref bodySpaceRay, radius, ref result); bool checkEdges = this.CircleCastEdges( ref bodySpaceRay, radius, ref result); // We need to check both to get the closest hit distance return(checkVertices || checkEdges); }
/// <summary> /// Tests all valid explosion targets for a given ray. /// </summary> private void TestTargets( VoltRayCast ray, VoltExplosionCallback callback, int ticksBehind, FP minOccluderDistance, FP rayWeight) { for (int i = 0; i < this.targetBodies.Count; i++) { VoltBody targetBody = this.targetBodies[i]; VoltRayResult result = default(VoltRayResult); if (targetBody.RayCast(ref ray, ref result, ticksBehind)) { if (result.Distance < minOccluderDistance) { callback.Invoke(ray, result, rayWeight); } } } }
/// <summary> /// Gets the distance to the closest occluder for the given ray. /// </summary> private FP GetOccludingDistance( VoltRayCast ray, int ticksBehind) { FP distance = FP.MaxValue; VoltRayResult result = default(VoltRayResult); for (int i = 0; i < this.occludingBodies.Count; i++) { if (this.occludingBodies[i].RayCast(ref ray, ref result, ticksBehind)) { distance = result.Distance; } if (result.IsContained) { break; } } return(distance); }
/// <summary> /// Performs a circle cast check on this body. /// Begins with AABB checks. /// </summary> internal bool CircleCast( ref VoltRayCast ray, FP radius, ref VoltRayResult result, int ticksBehind, bool bypassAABB = false) { HistoryRecord record = this.GetState(ticksBehind); // AABB check done in world space (because it keeps changing) if (bypassAABB == false) { if (record.aabb.CircleCastApprox(ref ray, radius) == false) { return(false); } } // Actual tests on shapes done in body space VoltRayCast bodySpaceRay = record.WorldToBodyRay(ref ray); for (int i = 0; i < this.shapeCount; i++) { if (this.shapes[i].CircleCast(ref bodySpaceRay, radius, ref result)) { if (result.IsContained) { return(true); } } } // We need to convert the results back to world space to be any use // (Doesn't matter if we were contained since there will be no normal) if (result.Body == this) { result.normal = record.BodyToWorldDirection(result.normal); } return(result.IsValid); }
protected abstract bool ShapeCircleCast( ref VoltRayCast bodySpaceRay, float radius, ref VoltRayResult result);
public void PerformExplosion( Vector2 origin, float radius, VoltExplosionCallback callback, VoltBodyFilter targetFilter = null, VoltBodyFilter occlusionFilter = null, int ticksBehind = 0, int rayCount = 32) { if (ticksBehind < 0) throw new ArgumentOutOfRangeException("ticksBehind"); // Get all target bodies this.PopulateFiltered( origin, radius, targetFilter, ticksBehind, ref this.targetBodies); // Get all occluding bodies this.PopulateFiltered( origin, radius, occlusionFilter, ticksBehind, ref this.occludingBodies); VoltRayCast ray; float rayWeight = 1.0f / rayCount; float angleIncrement = (Mathf.PI * 2.0f) * rayWeight; for (int i = 0; i < rayCount; i++) { Vector2 normal = VoltMath.Polar(angleIncrement * i); ray = new VoltRayCast(origin, normal, radius); float minDistance = this.GetOccludingDistance(ray, ticksBehind); minDistance += VoltWorld.EXPLOSION_OCCLUDER_SLOP; this.TestTargets(ray, callback, ticksBehind, minDistance, rayWeight); } }
protected override bool ShapeCircleCast( ref VoltRayCast bodySpaceRay, float radius, ref VoltRayResult result) { bool checkVertices = this.CircleCastVertices( ref bodySpaceRay, radius, ref result); bool checkEdges = this.CircleCastEdges( ref bodySpaceRay, radius, ref result); // We need to check both to get the closest hit distance return checkVertices || checkEdges; }
protected abstract bool ShapeRayCast( ref VoltRayCast bodySpaceRay, ref VoltRayResult result);
private bool CircleCastEdges( ref VoltRayCast bodySpaceRay, float radius, ref VoltRayResult result) { int foundIndex = -1; bool couldBeContained = true; // Pre-compute and initialize values float shortestDist = float.MaxValue; Vector2 v3 = bodySpaceRay.direction.Left(); // Check the edges -- this will be different from the raycast because // we care about staying within the ends of the edge line segment for (int i = 0; i < this.countBody; i++) { Axis curAxis = this.bodyAxes[i]; // Push the edges out by the radius Vector2 extension = curAxis.Normal * radius; Vector2 a = this.bodyVertices[i] + extension; Vector2 b = this.bodyVertices[(i + 1) % this.countBody] + extension; // Update the check for containment if (couldBeContained == true) { float proj = Vector2.Dot(curAxis.Normal, bodySpaceRay.origin) - curAxis.Width; // The point lies outside of the outer layer if (proj > radius) { couldBeContained = false; } // The point lies between the outer and inner layer else if (proj > 0.0f) { // See if the point is within the center Vornoi region of the edge float d = VoltMath.Cross(curAxis.Normal, bodySpaceRay.origin); if (d > VoltMath.Cross(curAxis.Normal, a)) { couldBeContained = false; } if (d < VoltMath.Cross(curAxis.Normal, b)) { couldBeContained = false; } } } // For the cast, only consider rays pointing towards the edge if (Vector2.Dot(curAxis.Normal, bodySpaceRay.direction) >= 0.0f) { continue; } // See: // https://rootllama.wordpress.com/2014/06/20/ray-line-segment-intersection-test-in-2d/ Vector2 v1 = bodySpaceRay.origin - a; Vector2 v2 = b - a; float denominator = Vector2.Dot(v2, v3); float t1 = VoltMath.Cross(v2, v1) / denominator; float t2 = Vector2.Dot(v1, v3) / denominator; if ((t2 >= 0.0f) && (t2 <= 1.0f) && (t1 > 0.0f) && (t1 < shortestDist)) { // See if the point is outside of any of the axes shortestDist = t1; foundIndex = i; } } // Report results if (couldBeContained == true) { result.SetContained(this); return(true); } else if (foundIndex >= 0 && shortestDist <= bodySpaceRay.distance) { result.Set( this, shortestDist, this.bodyAxes[foundIndex].Normal); return(true); } return(false); }
protected override bool ShapeRayCast( ref VoltRayCast bodySpaceRay, ref VoltRayResult result) { int foundIndex = -1; float inner = float.MaxValue; float outer = 0; bool couldBeContained = true; for (int i = 0; i < this.countBody; i++) { Axis curAxis = this.bodyAxes[i]; // Distance between the ray origin and the axis/edge along the // normal (i.e., shortest distance between ray origin and the edge) float proj = Vector2.Dot(curAxis.Normal, bodySpaceRay.origin) - curAxis.Width; // See if the point is outside of any of the axes if (proj > 0.0f) couldBeContained = false; // Projection of the ray direction onto the axis normal (use // negative normal because we want to get the penetration length) float slope = Vector2.Dot(-curAxis.Normal, bodySpaceRay.direction); if (slope == 0.0f) continue; float dist = proj / slope; // The ray is pointing opposite the edge normal (towards the edge) if (slope > 0.0f) { if (dist > inner) { return false; } if (dist > outer) { outer = dist; foundIndex = i; } } // The ray is pointing along the edge normal (away from the edge) else { if (dist < outer) { return false; } if (dist < inner) { inner = dist; } } } if (couldBeContained == true) { result.SetContained(this); return true; } else if (foundIndex >= 0 && outer <= bodySpaceRay.distance) { result.Set( this, outer, this.bodyAxes[foundIndex].Normal); return true; } return false; }
public Vector2 ComputePoint(ref VoltRayCast cast) { return cast.origin + (cast.direction * this.distance); }
protected override bool ShapeRayCast( ref VoltRayCast bodySpaceRay, ref VoltRayResult result) { int foundIndex = -1; float inner = float.MaxValue; float outer = 0; bool couldBeContained = true; for (int i = 0; i < this.countBody; i++) { Axis curAxis = this.bodyAxes[i]; // Distance between the ray origin and the axis/edge along the // normal (i.e., shortest distance between ray origin and the edge) float proj = Vector2.Dot(curAxis.Normal, bodySpaceRay.origin) - curAxis.Width; // See if the point is outside of any of the axes if (proj > 0.0f) { couldBeContained = false; } // Projection of the ray direction onto the axis normal (use // negative normal because we want to get the penetration length) float slope = Vector2.Dot(-curAxis.Normal, bodySpaceRay.direction); if (slope == 0.0f) { continue; } float dist = proj / slope; // The ray is pointing opposite the edge normal (towards the edge) if (slope > 0.0f) { if (dist > inner) { return(false); } if (dist > outer) { outer = dist; foundIndex = i; } } // The ray is pointing along the edge normal (away from the edge) else { if (dist < outer) { return(false); } if (dist < inner) { inner = dist; } } } if (couldBeContained == true) { result.SetContained(this); return(true); } else if (foundIndex >= 0 && outer <= bodySpaceRay.distance) { result.Set( this, outer, this.bodyAxes[foundIndex].Normal); return(true); } return(false); }
/// <summary> /// Note: This doesn't take rounded edges into account. /// </summary> public bool CircleCastApprox(ref VoltRayCast ray, float radius) { return VoltAABB.RayCast( ref ray, this.top + radius, this.bottom - radius, this.left - radius, this.right + radius); }
/// <summary> /// Performs a raycast on all world bodies. /// </summary> public bool RayCast( ref VoltRayCast ray, ref VoltRayResult result, VoltBodyFilter filter = null, int ticksBehind = 0) { if (ticksBehind < 0) throw new ArgumentOutOfRangeException("ticksBehind"); this.reusableBuffer.Clear(); this.staticBroadphase.RayCast(ref ray, this.reusableBuffer); this.dynamicBroadphase.RayCast(ref ray, this.reusableBuffer); for (int i = 0; i < this.reusableBuffer.Count; i++) { VoltBody body = this.reusableBuffer[i]; if (VoltBody.Filter(body, filter)) { body.RayCast(ref ray, ref result, ticksBehind); if (result.IsContained) return true; } } return result.IsValid; }
public void RayCast( ref VoltRayCast ray, VoltBuffer <VoltBody> outBuffer) { outBuffer.Add(this.bodies, this.count); }
public bool RayCast(ref VoltRayCast ray) { return VoltAABB.RayCast( ref ray, this.top, this.bottom, this.left, this.right); }
/// <summary> /// A cheap ray test that requires some precomputed information. /// Adapted from: http://www.cs.utah.edu/~awilliam/box/box.pdf /// </summary> private static bool RayCast( ref VoltRayCast ray, float top, float bottom, float left, float right) { float txmin = ((ray.signX ? right : left) - ray.origin.x) * ray.invDirection.x; float txmax = ((ray.signX ? left : right) - ray.origin.x) * ray.invDirection.x; float tymin = ((ray.signY ? top : bottom) - ray.origin.y) * ray.invDirection.y; float tymax = ((ray.signY ? bottom : top) - ray.origin.y) * ray.invDirection.y; if ((txmin > tymax) || (tymin > txmax)) return false; if (tymin > txmin) txmin = tymin; if (tymax < txmax) txmax = tymax; return (txmax > 0.0f) && (txmin < ray.distance); }
public void RayCast( ref VoltRayCast ray, VoltBuffer<VoltBody> outBuffer) { outBuffer.Add(this.bodies, this.count); }
private bool CircleCastVertices( ref VoltRayCast bodySpaceRay, float radius, ref VoltRayResult result) { float sqrRadius = radius * radius; bool castHit = false; for (int i = 0; i < this.countBody; i++) { castHit |= Collision.CircleRayCast( this, this.bodyVertices[i], sqrRadius, ref bodySpaceRay, ref result); if (result.IsContained == true) return true; } return castHit; }
/// <summary> /// Tests all valid explosion targets for a given ray. /// </summary> private void TestTargets( VoltRayCast ray, VoltExplosionCallback callback, int ticksBehind, float minOccluderDistance, float rayWeight) { for (int i = 0; i < this.targetBodies.Count; i++) { VoltBody targetBody = this.targetBodies[i]; VoltRayResult result = default(VoltRayResult); if (targetBody.RayCast(ref ray, ref result, ticksBehind)) if (result.Distance < minOccluderDistance) callback.Invoke(ray, result, rayWeight); } }
private bool CircleCastEdges( ref VoltRayCast bodySpaceRay, float radius, ref VoltRayResult result) { int foundIndex = -1; bool couldBeContained = true; // Pre-compute and initialize values float shortestDist = float.MaxValue; Vector2 v3 = bodySpaceRay.direction.Left(); // Check the edges -- this will be different from the raycast because // we care about staying within the ends of the edge line segment for (int i = 0; i < this.countBody; i++) { Axis curAxis = this.bodyAxes[i]; // Push the edges out by the radius Vector2 extension = curAxis.Normal * radius; Vector2 a = this.bodyVertices[i] + extension; Vector2 b = this.bodyVertices[(i + 1) % this.countBody] + extension; // Update the check for containment if (couldBeContained == true) { float proj = Vector2.Dot(curAxis.Normal, bodySpaceRay.origin) - curAxis.Width; // The point lies outside of the outer layer if (proj > radius) { couldBeContained = false; } // The point lies between the outer and inner layer else if (proj > 0.0f) { // See if the point is within the center Vornoi region of the edge float d = VoltMath.Cross(curAxis.Normal, bodySpaceRay.origin); if (d > VoltMath.Cross(curAxis.Normal, a)) couldBeContained = false; if (d < VoltMath.Cross(curAxis.Normal, b)) couldBeContained = false; } } // For the cast, only consider rays pointing towards the edge if (Vector2.Dot(curAxis.Normal, bodySpaceRay.direction) >= 0.0f) continue; // See: // https://rootllama.wordpress.com/2014/06/20/ray-line-segment-intersection-test-in-2d/ Vector2 v1 = bodySpaceRay.origin - a; Vector2 v2 = b - a; float denominator = Vector2.Dot(v2, v3); float t1 = VoltMath.Cross(v2, v1) / denominator; float t2 = Vector2.Dot(v1, v3) / denominator; if ((t2 >= 0.0f) && (t2 <= 1.0f) && (t1 > 0.0f) && (t1 < shortestDist)) { // See if the point is outside of any of the axes shortestDist = t1; foundIndex = i; } } // Report results if (couldBeContained == true) { result.SetContained(this); return true; } else if (foundIndex >= 0 && shortestDist <= bodySpaceRay.distance) { result.Set( this, shortestDist, this.bodyAxes[foundIndex].Normal); return true; } return false; }
public void CircleCast( ref VoltRayCast ray, float radius, VoltBuffer<VoltBody> outBuffer) { this.StartQuery(outBuffer); while (this.queryStack.Count > 0) { Node node = this.GetNextNode(); if (node.aabb.CircleCastApprox(ref ray, radius)) this.ExpandNode(node, outBuffer); } }
/// <summary> /// Gets the distance to the closest occluder for the given ray. /// </summary> private float GetOccludingDistance( VoltRayCast ray, int ticksBehind) { float distance = float.MaxValue; VoltRayResult result = default(VoltRayResult); for (int i = 0; i < this.occludingBodies.Count; i++) { if (this.occludingBodies[i].RayCast(ref ray, ref result, ticksBehind)) distance = result.Distance; if (result.IsContained) break; } return distance; }
public VoltVector2 ComputePoint(ref VoltRayCast cast) { return(cast.origin + (cast.direction * this.distance)); }
public void RayCast( ref VoltRayCast ray, VoltBuffer<VoltBody> outBuffer) { this.StartQuery(outBuffer); while (this.queryStack.Count > 0) { Node node = this.GetNextNode(); if (node.aabb.RayCast(ref ray)) this.ExpandNode(node, outBuffer); } }