private void PrepareQueryObject(EntityCollidable queryObject, ref System.Numerics.Vector3 position) { RigidTransform transform; transform.Position = position; transform.Orientation = characterBody.Orientation; queryObject.UpdateBoundingBoxForTransform(ref transform, 0); }
private void QueryContacts(Vector3 position, EntityCollidable queryObject) { this.ClearContacts(); //Update the position and orientation of the query object. RigidTransform transform; transform.Position = position; transform.Orientation = this.character.Body.Orientation; queryObject.UpdateBoundingBoxForTransform(ref transform, 0); foreach (var collidable in this.character.Body.CollisionInformation.OverlappedCollidables) { if (collidable.BoundingBox.Intersects(queryObject.BoundingBox)) { var pair = new CollidablePair(collidable, queryObject); var pairHandler = NarrowPhaseHelper.GetPairHandler(ref pair); if (pairHandler.CollisionRule == CollisionRule.Normal) { pairHandler.SuppressEvents = true; pairHandler.UpdateCollision(0); pairHandler.SuppressEvents = false; foreach (var contact in pairHandler.Contacts) { //Must check per-contact collision rules, just in case //the pair was actually a 'parent pair.' if (contact.Pair.CollisionRule == CollisionRule.Normal) { ContactData contactData; contactData.Position = contact.Contact.Position; contactData.Normal = contact.Contact.Normal; contactData.Id = contact.Contact.Id; contactData.PenetrationDepth = contact.Contact.PenetrationDepth; this.contacts.Add(contactData); } } } //TODO: It would be nice if this was a bit easier. //Having to remember to clean up AND give it back is a bit weird, especially with the property-diving. //No one would ever just guess this correctly. //At least hide it behind a NarrowPhaseHelper function. pairHandler.CleanUp(); pairHandler.Factory.GiveBack(pairHandler); } } this.CategorizeContacts(ref position); }
public override void SpawnBody() { PreHandleSpawn(); base.SpawnBody(); if (mode == ModelCollisionMode.PRECISE) { Offset = InternalOffset; } BEPUutilities.Vector3 offs = Offset.ToBVector(); transform = Matrix4d.CreateTranslation(ClientUtilities.ConvertD(Offset)); List<BEPUutilities.Vector3> tvecs = TheClient.Models.Handler.GetVertices(model.Original); if (tvecs.Count == 0) { ModelMin = new BEPUutilities.Vector3(0, 0, 0); ModelMax = new BEPUutilities.Vector3(0, 0, 0); } else { ModelMin = tvecs[0]; ModelMax = tvecs[0]; foreach (BEPUutilities.Vector3 vec in tvecs) { BEPUutilities.Vector3 tvec = vec + offs; if (tvec.X < ModelMin.X) { ModelMin.X = tvec.X; } if (tvec.Y < ModelMin.Y) { ModelMin.Y = tvec.Y; } if (tvec.Z < ModelMin.Z) { ModelMin.Z = tvec.Z; } if (tvec.X > ModelMax.X) { ModelMax.X = tvec.X; } if (tvec.Y > ModelMax.Y) { ModelMax.Y = tvec.Y; } if (tvec.Z > ModelMax.Z) { ModelMax.Z = tvec.Z; } } } if (GenBlockShadows) { double tx = ModelMax.X - ModelMin.X; double ty = ModelMax.Y - ModelMin.Y; BoxShape bs = new BoxShape(tx, ty, ModelMax.Z - ModelMin.Z); EntityCollidable tempCast = bs.GetCollidableInstance(); tempCast.LocalPosition = (ModelMax + ModelMin) * 0.5f + Body.Position; RigidTransform def = RigidTransform.Identity; tempCast.UpdateBoundingBoxForTransform(ref def); ShadowCastShape = tempCast.BoundingBox; BEPUutilities.Vector3 size = ShadowCastShape.Max - ShadowCastShape.Min; ShadowRadiusSquaredXY = size.X * size.X + size.Y * size.Y; } }
public bool ConvexCast(ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweepnorm, double slen, MaterialSolidity solidness, out RayHit hit) { RigidTransform rot = new RigidTransform(Vector3.Zero, startingTransform.Orientation); castShape.GetBoundingBox(ref rot, out BoundingBox bb); double adv = 0.1f; double max = slen + adv; bool gotOne = false; RayHit BestRH = default(RayHit); Vector3 sweep = sweepnorm * slen; for (double f = 0; f < max; f += adv) { Vector3 c = startingTransform.Position + sweepnorm * f; int mx = (int)Math.Ceiling(c.X + bb.Max.X); for (int x = (int)Math.Floor(c.X + bb.Min.X); x <= mx; x++) { if (x < 0 || x >= ChunkSize.X) { continue; } int my = (int)Math.Ceiling(c.Y + bb.Max.Y); for (int y = (int)Math.Floor(c.Y + bb.Min.Y); y <= my; y++) { if (y < 0 || y >= ChunkSize.Y) { continue; } int mz = (int)Math.Ceiling(c.Z + bb.Max.Z); for (int z = (int)Math.Floor(c.Z + bb.Min.Z); z <= mz; z++) { if (z < 0 || z >= ChunkSize.Z) { continue; } BlockInternal bi = Blocks[BlockIndex(x, y, z)]; if (solidness.HasFlag(((Material)bi.BlockMaterial).GetSolidity())) { EntityShape es = BlockShapeRegistry.BSD[bi.BlockData].GetShape(bi.Damage, out Location offs, false); if (es == null) { continue; } Vector3 adj = new Vector3(x + (double)offs.X, y + (double)offs.Y, z + (double)offs.Z); EntityCollidable coll = es.GetCollidableInstance(); //coll.LocalPosition = adj; RigidTransform rt = new RigidTransform(Vector3.Zero, Quaternion.Identity); coll.LocalPosition = Vector3.Zero; coll.WorldTransform = rt; coll.UpdateBoundingBoxForTransform(ref rt); RigidTransform adjusted = new RigidTransform(startingTransform.Position - adj, startingTransform.Orientation); bool b = coll.ConvexCast(castShape, ref adjusted, ref sweep, out RayHit rhit); if (b && (!gotOne || rhit.T * slen < BestRH.T) && rhit.T >= 0) { gotOne = true; BestRH = rhit; BestRH.Location += adj; BestRH.T *= slen; // TODO: ??? BestRH.Normal = -BestRH.Normal; // TODO: WHY?! } } } } } if (gotOne) { hit = BestRH; return(true); } } hit = new RayHit() { Location = startingTransform.Position + sweep, Normal = new Vector3(0, 0, 0), T = slen }; return(false); }