/// <summary> /// Finds all bodies intersecting with a given circle. /// /// Subsequent calls to other Query functions (Point, Circle, Bounds) will /// invalidate the resulting enumeration from this function. /// </summary> public VoltBuffer <VoltBody> QueryCircle( VoltVector2 origin, Fix64 radius, VoltBodyFilter filter = null, int ticksBehind = 0) { if (ticksBehind < 0) { throw new ArgumentOutOfRangeException("ticksBehind"); } this.reusableBuffer.Clear(); this.staticBroadphase.QueryCircle(origin, radius, this.reusableBuffer); this.dynamicBroadphase.QueryCircle(origin, radius, this.reusableBuffer); this.reusableOutput.Clear(); for (int i = 0; i < this.reusableBuffer.Count; i++) { VoltBody body = this.reusableBuffer[i]; if (VoltBody.Filter(body, filter)) { if (body.QueryCircle(origin, radius, ticksBehind)) { this.reusableOutput.Add(body); } } } return(this.reusableOutput); }
/// <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); }
/// <summary> /// Finds all dynamic bodies that overlap with the explosion AABB /// and pass the target filter test. Does not test actual shapes. /// </summary> private void PopulateFiltered( TSVector2 origin, FP radius, VoltBodyFilter targetFilter, int ticksBehind, ref VoltBuffer <VoltBody> filterBuffer) { if (filterBuffer == null) { filterBuffer = new VoltBuffer <VoltBody>(); } filterBuffer.Clear(); this.reusableBuffer.Clear(); this.staticBroadphase.QueryCircle(origin, radius, this.reusableBuffer); this.dynamicBroadphase.QueryCircle(origin, radius, this.reusableBuffer); VoltAABB aabb = new VoltAABB(origin, radius); for (int i = 0; i < this.reusableBuffer.Count; i++) { VoltBody body = this.reusableBuffer[i]; if ((targetFilter == null) || targetFilter.Invoke(body)) { if (body.QueryAABBOnly(aabb, ticksBehind)) { filterBuffer.Add(body); } } } }
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); } }
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); } }
public static bool Filter(VoltBody body, VoltBodyFilter filter) { return((filter == null) || (filter.Invoke(body) == true)); }
/// <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; }
/// <summary> /// Finds all bodies containing a given point. /// /// Subsequent calls to other Query functions (Point, Circle, Bounds) will /// invalidate the resulting enumeration from this function. /// </summary> public VoltBuffer<VoltBody> QueryPoint( Vector2 point, VoltBodyFilter filter = null, int ticksBehind = 0) { if (ticksBehind < 0) throw new ArgumentOutOfRangeException("ticksBehind"); this.reusableBuffer.Clear(); this.staticBroadphase.QueryPoint(point, this.reusableBuffer); this.dynamicBroadphase.QueryPoint(point, this.reusableBuffer); this.reusableOutput.Clear(); for (int i = 0; i < this.reusableBuffer.Count; i++) { VoltBody body = this.reusableBuffer[i]; if (VoltBody.Filter(body, filter)) if (body.QueryPoint(point, ticksBehind)) this.reusableOutput.Add(body); } return this.reusableOutput; }
/// <summary> /// Finds all dynamic bodies that overlap with the explosion AABB /// and pass the target filter test. Does not test actual shapes. /// </summary> private void PopulateFiltered( Vector2 origin, float radius, VoltBodyFilter targetFilter, int ticksBehind, ref VoltBuffer<VoltBody> filterBuffer) { if (filterBuffer == null) filterBuffer = new VoltBuffer<VoltBody>(); filterBuffer.Clear(); this.reusableBuffer.Clear(); this.staticBroadphase.QueryCircle(origin, radius, this.reusableBuffer); this.dynamicBroadphase.QueryCircle(origin, radius, this.reusableBuffer); VoltAABB aabb = new VoltAABB(origin, radius); for (int i = 0; i < this.reusableBuffer.Count; i++) { VoltBody body = this.reusableBuffer[i]; if ((targetFilter == null) || targetFilter.Invoke(body)) if (body.QueryAABBOnly(aabb, ticksBehind)) filterBuffer.Add(body); } }