/// <summary> /// Creates a bounding box from a bounding sphere. /// </summary> /// <param name="boundingSphere">Bounding sphere to be used to create the bounding box.</param> /// <param name="boundingBox">Bounding box created from the bounding sphere.</param> public static void CreateFromSphere(ref BoundingSphere boundingSphere, out BoundingBox boundingBox) { boundingBox.Min.X = boundingSphere.Center.X - boundingSphere.Radius; boundingBox.Min.Y = boundingSphere.Center.Y - boundingSphere.Radius; boundingBox.Min.Z = boundingSphere.Center.Z - boundingSphere.Radius; boundingBox.Max.X = boundingSphere.Center.X + boundingSphere.Radius; boundingBox.Max.Y = boundingSphere.Center.Y + boundingSphere.Radius; boundingBox.Max.Z = boundingSphere.Center.Z + boundingSphere.Radius; }
public void GetEntries(BoundingSphere boundingShape, IList<BroadPhaseEntry> overlaps) { //Create a bounding box based on the bounding sphere. //Compute the min and max of the bounding box. //Loop through the cells and select bounding boxes which overlap the x axis. #if !WINDOWS System.Numerics.Vector3 offset = new System.Numerics.Vector3(); #else System.Numerics.Vector3 offset; #endif offset.X = boundingShape.Radius; offset.Y = offset.X; offset.Z = offset.Y; BoundingBox box; Vector3Ex.Add(ref boundingShape.Center, ref offset, out box.Max); Vector3Ex.Subtract(ref boundingShape.Center, ref offset, out box.Min); Int2 min, max; Grid2DSortAndSweep.ComputeCell(ref box.Min, out min); Grid2DSortAndSweep.ComputeCell(ref box.Max, out max); for (int i = min.Y; i <= max.Y; i++) { for (int j = min.Z; j <= max.Z; j++) { //Grab the cell that we are currently in. Int2 cellIndex; cellIndex.Y = i; cellIndex.Z = j; GridCell2D cell; if (owner.cellSet.TryGetCell(ref cellIndex, out cell)) { //To fully accelerate this, the entries list would need to contain both min and max interval markers. //Since it only contains the sorted min intervals, we can't just start at a point in the middle of the list. //Consider some giant bounding box that spans the entire list. for (int k = 0; k < cell.entries.Count && cell.entries.Elements[k].item.boundingBox.Min.X <= box.Max.X; k++) //TODO: Try additional x axis pruning? A bit of optimization potential due to overlap with AABB test. { bool intersects; var item = cell.entries.Elements[k].item; item.boundingBox.Intersects(ref boundingShape, out intersects); if (intersects && !overlaps.Contains(item)) { overlaps.Add(item); } } } } } }
private void OnInputEvent(ReadOnlyCollection <SInputButtonEvent> buttonevents, string textinput) { foreach (var buttonEvent in buttonevents) { if (buttonEvent.button == EInputButton.MouseMiddleButton && buttonEvent.buttonEvent == EButtonEvent.Pressed) { CViewManager viewManager = m_gameWorld.ViewManager; int mouseAbsX = System.Windows.Forms.Cursor.Position.X - (int)viewManager.ScreenLeft; int mouseAbsY = System.Windows.Forms.Cursor.Position.Y - (int)viewManager.ScreenTop; if (mouseAbsX < 0 || mouseAbsY < 0) { return; } viewManager.GetViewInfo(out SSceneViewInfo viewInfo); Ray pickRay = Ray.GetPickRay(mouseAbsX, mouseAbsY, new ViewportF(0, 0, viewManager.ScreenWidth, viewManager.ScreenHeight), viewInfo.ViewMatrix * viewInfo.ProjectionMatrix); if (m_physicSpace.RayCast(pickRay.ToBepu(), 9999.0f, out RayCastResult result)) { float fieldRadius = 5.0f; float impulseStrength = 20.0f; List <BroadPhaseEntry> queryResults = new List <BroadPhaseEntry>(); BoundingSphere bs = new BoundingSphere(result.HitData.Location, fieldRadius); m_physicSpace.BroadPhase.QueryAccelerator.GetEntries(bs, queryResults); foreach (var entry in queryResults) { var entityCollision = entry as EntityCollidable; if (entityCollision != null) { var e = entityCollision.Entity; if (e.IsDynamic) { Vector3 toEntity = e.Position - result.HitData.Location; float length = toEntity.Length(); float strength = impulseStrength / length; toEntity.Y = 1.0f; toEntity.Normalize(); e.ApplyImpulse(e.Position, toEntity * strength); } } } } } } }
/// <summary> /// Returns the list of ConvexCollidable's and Entities inside or touching the specified sphere. /// Result does not include static geometry and non-entity physical objects. /// </summary> /// <param name="world"></param> /// <param name="origin"></param> /// <param name="radius"></param> /// <returns></returns> public List <Entity> WeaponOverlap(Vector3 origin, float radius, Entity entToSkip) { BU.BoundingSphere sphere = new BU.BoundingSphere(MathConverter.Convert(origin), radius); SphereShape sphereShape = new SphereShape(radius); BU.Vector3 zeroSweep = BU.Vector3.Zero; BU.RigidTransform rigidXForm = new BU.RigidTransform(MathConverter.Convert(origin)); var candidates = PhysicsResources.GetBroadPhaseEntryList(); PhysSpace.BroadPhase.QueryAccelerator.BroadPhase.QueryAccelerator.GetEntries(sphere, candidates); var result = new List <Entity>(); foreach (var candidate in candidates) { BU.RayHit rayHit; bool r = candidate.ConvexCast(sphereShape, ref rigidXForm, ref zeroSweep, out rayHit); if (r) { var collidable = candidate as ConvexCollidable; var entity = collidable == null ? null : collidable.Entity.Tag as Entity; if (collidable == null) { continue; } if (entity == null) { continue; } result.Add(entity); } } result.RemoveAll(e => e == entToSkip); return(result); }
/// <summary> /// Constructs a new force field shape using a bounding sphere. /// </summary> /// <param name="sphere">Bounding sphere to use.</param> public BoundingSphereForceFieldShape(BoundingSphere sphere) { BoundingSphere = sphere; }
/// <summary> /// Determines if a bounding box intersects a bounding sphere. /// </summary> /// <param name="boundingSphere">Sphere to test for intersection.</param> /// <param name="intersects">Whether the bounding shapes intersect.</param> public void Intersects(ref BoundingSphere boundingSphere, out bool intersects) { Vector3 clampedLocation; if (boundingSphere.Center.X > Max.X) clampedLocation.X = Max.X; else if (boundingSphere.Center.X < Min.X) clampedLocation.X = Min.X; else clampedLocation.X = boundingSphere.Center.X; if (boundingSphere.Center.Y > Max.Y) clampedLocation.Y = Max.Y; else if (boundingSphere.Center.Y < Min.Y) clampedLocation.Y = Min.Y; else clampedLocation.Y = boundingSphere.Center.Y; if (boundingSphere.Center.Z > Max.Z) clampedLocation.Z = Max.Z; else if (boundingSphere.Center.Z < Min.Z) clampedLocation.Z = Min.Z; else clampedLocation.Z = boundingSphere.Center.Z; float distanceSquared; Vector3.DistanceSquared(ref clampedLocation, ref boundingSphere.Center, out distanceSquared); intersects = distanceSquared <= boundingSphere.Radius * boundingSphere.Radius; }
/// <summary> /// Gets the triangles whose bounding boxes are overlapped by the query. /// </summary> /// <param name="boundingSphere">Shape to query against the tree.</param> /// <param name="outputOverlappedElements">Indices of triangles in the index buffer with bounding boxes which are overlapped by the query.</param> /// <returns>Whether or not any elements were overlapped.</returns> public bool GetOverlaps(BoundingSphere boundingSphere, IList<int> outputOverlappedElements) { if (root != null) { bool intersects; root.BoundingBox.Intersects(ref boundingSphere, out intersects); if (intersects) root.GetOverlaps(ref boundingSphere, outputOverlappedElements); } return outputOverlappedElements.Count > 0; }
internal abstract void GetOverlaps(ref BoundingSphere boundingSphere, IList<int> outputOverlappedElements);
internal override void GetOverlaps(ref BoundingSphere boundingSphere, IList<int> outputOverlappedElements) { outputOverlappedElements.Add(LeafIndex); }
internal override void GetOverlaps(ref BoundingSphere boundingSphere, IList<int> outputOverlappedElements) { bool intersects; ChildA.BoundingBox.Intersects(ref boundingSphere, out intersects); if (intersects) ChildA.GetOverlaps(ref boundingSphere, outputOverlappedElements); ChildB.BoundingBox.Intersects(ref boundingSphere, out intersects); if (intersects) ChildB.GetOverlaps(ref boundingSphere, outputOverlappedElements); }
/// <summary> /// Returns the list of ConvexCollidable's and Entities inside or touching the specified sphere. /// Result does not include static geometry and non-entity physical objects. /// </summary> /// <param name="world"></param> /// <param name="origin"></param> /// <param name="radius"></param> /// <returns></returns> public List<Entity> WeaponOverlap( Vector3 origin, float radius, Entity entToSkip ) { BU.BoundingSphere sphere = new BU.BoundingSphere(MathConverter.Convert(origin), radius); SphereShape sphereShape = new SphereShape(radius); BU.Vector3 zeroSweep = BU.Vector3.Zero; BU.RigidTransform rigidXForm = new BU.RigidTransform( MathConverter.Convert(origin) ); var candidates = PhysicsResources.GetBroadPhaseEntryList(); physSpace.BroadPhase.QueryAccelerator.BroadPhase.QueryAccelerator.GetEntries(sphere, candidates); var result = new List<Entity>(); foreach ( var candidate in candidates ) { BU.RayHit rayHit; bool r = candidate.ConvexCast( sphereShape, ref rigidXForm, ref zeroSweep, out rayHit ); if (r) { var collidable = candidate as ConvexCollidable; var entity = collidable==null ? null : collidable.Entity.Tag as Entity; if (collidable==null) continue; if (entity==null) continue; result.Add( entity ); } } result.RemoveAll( e => e == entToSkip ); return result; }
///// <summary> ///// Collects all entries with bounding boxes which intersect the given frustum. ///// </summary> ///// <param name="frustum">Frustum to test against the world.</param> ///// <param name="entries">Entries of the space which intersect the frustum.</param> //public void GetEntries(BoundingFrustum frustum, IList<BroadPhaseEntry> entries) //{ // if (hierarchy.root != null) // hierarchy.root.GetOverlaps(ref frustum, entries); //} /// <summary> /// Collects all entries with bounding boxes which intersect the given sphere. /// </summary> /// <param name="sphere">Sphere to test against the world.</param> /// <param name="entries">Entries of the space which intersect the sphere.</param> public void GetEntries(BoundingSphere sphere, IList<BroadPhaseEntry> entries) { if (hierarchy.root != null) hierarchy.root.GetOverlaps(ref sphere, entries); }