public BSD0() { BlockShapeCache = new BoxShape(1f, 1f, 1f); OffsetCache = new Location(0.5); ShrunkBlockShapeCache = new BoxShape(SHRINK_CONSTANT, SHRINK_CONSTANT, SHRINK_CONSTANT); ShrunkOffsetCache = new Location(SHRINK_CONSTANT * 0.5); }
public bool HassSolidEntity(Location min, Location max) { // TODO: Better alg! BoundingBox bb = new BoundingBox(min.ToBVector(), max.ToBVector()); List<BroadPhaseEntry> entries = new List<BroadPhaseEntry>(); PhysicsWorld.BroadPhase.QueryAccelerator.GetEntries(bb, entries); if (entries.Count == 0) { return false; } Location center = (max + min) * 0.5; Location rel = max - min; BoxShape box = new BoxShape((double)rel.X, (double)rel.Y, (double)rel.Z); RigidTransform start = new RigidTransform(center.ToBVector(), Quaternion.Identity); Vector3 sweep = new Vector3(0, 0, 0.01f); RayHit rh; foreach (BroadPhaseEntry entry in entries) { if (entry is EntityCollidable && Collision.ShouldCollide(entry) && entry.CollisionRules.Group != CollisionUtil.Player && entry.ConvexCast(box, ref start, ref sweep, out rh)) { return true; } } return false; }
public BSD01_5(double perc) { Percent = perc; OffsetCache = new Location(0.5, 0.5, Percent * 0.5); BlockShapeCache = new BoxShape(1, 1, Percent); ShrunkOffsetCache = new Location(SHRINK_CONSTANT * 0.5, SHRINK_CONSTANT * 0.5, Percent * SHRINK_CONSTANT * 0.5); ShrunkBlockShapeCache = new BoxShape(SHRINK_CONSTANT, SHRINK_CONSTANT, Percent * SHRINK_CONSTANT); }
public BSD64_68(params MaterialSide[] mats) { Mats = mats; BlockShapeCache = new BoxShape(1f, 1f, 1f); OffsetCache = new Location(0.5); ShrunkBlockShapeCache = new BoxShape(SHRINK_CONSTANT, SHRINK_CONSTANT, SHRINK_CONSTANT); ShrunkOffsetCache = new Location(SHRINK_CONSTANT * 0.5); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public AddRemoveStressDemo(DemosGame game) : base(game) { Space.Remove(vehicle.Vehicle); var compoundShape = new CompoundShape(new List<CompoundShapeEntry> { new CompoundShapeEntry(new BoxShape(1, 1, 1), new Vector3(0, 1, 0), 1), new CompoundShapeEntry(new BoxShape(2, 1, 2), new Vector3(), 1), new CompoundShapeEntry(new BoxShape(1, 1, 1), new Vector3(0, -1, 0), 1) }); for (int i = 0; i < 300; ++i) { var toAdd = new Entity(compoundShape, 10); addedEntities.Add(toAdd); } var boxShape = new BoxShape(1, 1, 1); for (int i = 0; i < 300; ++i) { var toAdd = new Entity(boxShape, 10); addedEntities.Add(toAdd); } Vector3[] vertices; int[] indices; ModelDataExtractor.GetVerticesAndIndicesFromModel(game.Content.Load<Model>("cube"), out vertices, out indices); var mobileMeshShape = new MobileMeshShape(vertices, indices, new AffineTransform(Matrix3x3.CreateScale(1, 2, 1), new Vector3()), MobileMeshSolidity.Counterclockwise); for (int i = 0; i < 300; ++i) { var toAdd = new Entity(mobileMeshShape, 10); addedEntities.Add(toAdd); } for (int i = 0; i < addedEntities.Count; ++i) { var entity = addedEntities[i]; entity.Gravity = new Vector3(); entity.Position = GetRandomPosition(random); entity.LinearVelocity = 3 * Vector3.Normalize(entity.Position); Space.Add(entity); } var playgroundModel = game.Content.Load<Model>("playground"); ModelDataExtractor.GetVerticesAndIndicesFromModel(playgroundModel, out vertices, out indices); var staticMesh = new StaticMesh(vertices, indices, new AffineTransform(Matrix3x3.CreateFromAxisAngle(Vector3.Up, MathHelper.Pi), new Vector3(0, -30, 0))); staticMesh.Sidedness = TriangleSidedness.Counterclockwise; Space.Add(staticMesh); game.ModelDrawer.Add(staticMesh); game.Camera.Position = new Vector3(0, 6, 15); }
public MobileChunkShape(Vector3i csize, BlockInternal[] blocks, out Vector3 center) { Matrix3x3 boxMat = new BoxShape(csize.X, csize.Y, csize.Z).VolumeDistribution; ChunkSize = csize; Blocks = blocks; double weightInv = 1f / blocks.Length; center = new Vector3(csize.X / 2f, csize.Y / 2f, csize.Z / 2f); // TODO: More accurately get center of weight based on which blocks are solid or not!? Matrix3x3 volumeDistribution = new Matrix3x3(); RigidTransform transform = new RigidTransform(center); Matrix3x3 contribution; CompoundShape.TransformContribution(ref transform, ref center, ref boxMat, blocks.Length, out contribution); Matrix3x3.Add(ref volumeDistribution, ref contribution, out volumeDistribution); Matrix3x3.Multiply(ref volumeDistribution, weightInv, out volumeDistribution); UpdateEntityShapeVolume(new EntityShapeVolumeDescription() { Volume = csize.X * csize.Y * csize.Z, VolumeDistribution = volumeDistribution }); Center = center; }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public MPRCastingDemo(DemosGame game) : base(game) { bShape = new BoxShape(1, 0, 1); //bShape.CollisionMargin = 0; aShape = new ConeShape(1, .4f); //aShape.CollisionMargin = 0; a = new Entity(aShape); b = new Entity(bShape); CollisionRules.AddRule(a, b, CollisionRule.NoSolver); NarrowPhaseHelper.CollisionManagers.Remove(new TypePair(typeof(ConvexCollidable<BoxShape>), typeof(ConvexCollidable<BoxShape>))); Space.Add(a); Space.Add(b); a.Orientation = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), MathHelper.PiOver4); b.Orientation = Quaternion.Identity; aTransform = new RigidTransform(new Vector3(-10, -10, -10), a.Orientation); bTransform = new RigidTransform(new Vector3(10, 10, 10), b.Orientation); game.Camera.Position = new Vector3(0, 5, 17); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public MPRTestDemo(DemosGame game) : base(game) { var shapeA = new BoxShape(1, 1, 1); shapeA.CollisionMargin = 0; var shapeB = new BoxShape(1, 1, 1); shapeB.CollisionMargin = 0; var transformA = new RigidTransform(new Vector3(0, 0, 0)); var transformB = new RigidTransform(new Vector3(.5f, .5f, 0)); Vector3 overlap; bool overlapped = MPRToolbox.GetLocalOverlapPosition(shapeA, shapeB, ref transformB, out overlap); Vector3 normal; float depth; Vector3 direction = new Vector3(0, -1, 0); MPRToolbox.LocalSurfaceCast(shapeA, shapeB, ref transformB, ref direction, out depth, out normal); ContactData contactData; //bool overlappedOld = MPRToolboxOld.AreObjectsColliding(shapeA, shapeB, ref transformA, ref transformB, out contactData); //Random rand = new Random(0); //for (int i = 0; i < 10000000; i++) //{ // transformA = new RigidTransform(new Vector3((float)rand.NextDouble() * 10 - 5, (float)rand.NextDouble() * 10 - 5, (float)rand.NextDouble() * 10 - 5), // Quaternion.CreateFromYawPitchRoll((float)rand.NextDouble() * 1000, (float)rand.NextDouble() * 1000, (float)rand.NextDouble() * 1000)); // transformB = new RigidTransform(new Vector3((float)rand.NextDouble() * 10 - 5, (float)rand.NextDouble() * 10 - 5, (float)rand.NextDouble() * 10 - 5), // Quaternion.CreateFromYawPitchRoll((float)rand.NextDouble() * 1000, (float)rand.NextDouble() * 1000, (float)rand.NextDouble() * 1000)); // overlapped = MPRTesting.GetOverlapPosition(shapeA, shapeB, ref transformA, ref transformB, out overlap); // overlappedOld = MPRToolbox.AreObjectsColliding(shapeA, shapeB, ref transformA, ref transformB, out contactData); // if (overlapped && !overlappedOld && // (!MPRToolbox.IsPointInsideShape(ref overlap, shapeA, ref transformA) || // !MPRToolbox.IsPointInsideShape(ref overlap, shapeB, ref transformB))) // Debug.WriteLine("Break."); // if (overlappedOld && !overlapped && // (!MPRToolbox.IsPointInsideShape(ref contactData.Position, shapeA, ref transformA) || // !MPRToolbox.IsPointInsideShape(ref contactData.Position, shapeB, ref transformB))) // Debug.WriteLine("Break."); // if (overlapped && overlappedOld && // (!MPRToolbox.IsPointInsideShape(ref overlap, shapeA, ref transformA) || // !MPRToolbox.IsPointInsideShape(ref overlap, shapeB, ref transformB) || // !MPRToolbox.IsPointInsideShape(ref contactData.Position, shapeA, ref transformA) || // !MPRToolbox.IsPointInsideShape(ref contactData.Position, shapeB, ref transformB))) // Debug.WriteLine("Break."); //} //Do these tests with rotationally immobile objects. CollisionDetectionSettings.DefaultMargin = 0; groundWidth = 10; groundHeight = .1f; groundLength = 10; //a = new Box(new Vector3(0, -5, 0), groundWidth, groundHeight, groundLength, 1); //a = new TransformableEntity(new Vector3(0,0,0), new TriangleShape(new Vector3(-5, -5, -5), new Vector3(5, -5, -5), new Vector3(-5, -5, 5)), Matrix3x3.Identity); a = new Triangle(new Vector3(0, -5, 0), new Vector3(5, -5, 0), new Vector3(5, -5, 5), 1); Space.Add(a); Space.ForceUpdater.Gravity = new Vector3(); boxWidth = .25f; boxHeight = .05f; boxLength = 1f; b = new TransformableEntity(new Vector3(0, 2, 0), new BoxShape(boxWidth, boxHeight, boxLength), Matrix3x3.Identity, 1); //b = new Cone(new Vector3(0, 2, 0), .2f, .1f, 1); //b = new Capsule(new Vector3(0, 2, 0), 1, .5f, 1); //b = new Capsule(new Vector3(0, 2, 0), 1, .5f, 1); b.LocalInertiaTensorInverse = new Matrix3x3(); CollisionRules.AddRule(b, a, CollisionRule.NoSolver); b.ActivityInformation.IsAlwaysActive = true; Space.Add(b); //Space.Add(new TransformableEntity(new Vector3(0, 4, 0), new BoxShape(1, 1, 1), Matrix3x3.Identity, 1)); //Space.Add( new TransformableEntity(new Vector3(0, 6, 0), new BoxShape(1, 1, 1), Matrix3x3.Identity, 1)); //Vector3[] vertices = new Vector3[] { new Vector3(0, -5, 0), new Vector3(5, -5, 0), new Vector3(5, -5, 5), new Vector3(0, -60, 5) }; //int[] indices = new int[] { 0, 1, 2 , 0, 2, 3 }; //StaticMesh mesh = new StaticMesh(vertices, indices); //Space.Add(mesh); //mesh.ImproveBoundaryBehavior = true; //mesh.Sidedness = TriangleSidedness.Counterclockwise; //game.ModelDrawer.Add(mesh); //mesh.CollisionRules.Personal = CollisionRule.NoSolver; }
///<summary> /// Tests if a box and sphere are colliding. ///</summary> ///<param name="box">Box to test.</param> ///<param name="sphere">Sphere to test.</param> ///<param name="boxTransform">Transform to apply to the box.</param> ///<param name="spherePosition">Transform to apply to the sphere.</param> ///<param name="contact">Contact point between the shapes, if any.</param> ///<returns>Whether or not the shapes were colliding.</returns> public static bool AreShapesColliding(BoxShape box, SphereShape sphere, ref RigidTransform boxTransform, ref Vector3 spherePosition, out ContactData contact) { contact = new ContactData(); Vector3 localPosition; RigidTransform.TransformByInverse(ref spherePosition, ref boxTransform, out localPosition); #if !WINDOWS Vector3 localClosestPoint = new Vector3(); #else Vector3 localClosestPoint; #endif localClosestPoint.X = MathHelper.Clamp(localPosition.X, -box.halfWidth, box.halfWidth); localClosestPoint.Y = MathHelper.Clamp(localPosition.Y, -box.halfHeight, box.halfHeight); localClosestPoint.Z = MathHelper.Clamp(localPosition.Z, -box.halfLength, box.halfLength); RigidTransform.Transform(ref localClosestPoint, ref boxTransform, out contact.Position); Vector3 offset; Vector3.Subtract(ref spherePosition, ref contact.Position, out offset); float offsetLength = offset.LengthSquared(); if (offsetLength > (sphere.collisionMargin + CollisionDetectionSettings.maximumContactDistance) * (sphere.collisionMargin + CollisionDetectionSettings.maximumContactDistance)) { return false; } //Colliding. if (offsetLength > Toolbox.Epsilon) { offsetLength = (float)Math.Sqrt(offsetLength); //Outside of the box. Vector3.Divide(ref offset, offsetLength, out contact.Normal); contact.PenetrationDepth = sphere.collisionMargin - offsetLength; } else { //Inside of the box. Vector3 penetrationDepths; penetrationDepths.X = localClosestPoint.X < 0 ? localClosestPoint.X + box.halfWidth : box.halfWidth - localClosestPoint.X; penetrationDepths.Y = localClosestPoint.Y < 0 ? localClosestPoint.Y + box.halfHeight : box.halfHeight - localClosestPoint.Y; penetrationDepths.Z = localClosestPoint.Z < 0 ? localClosestPoint.Z + box.halfLength : box.halfLength - localClosestPoint.Z; if (penetrationDepths.X < penetrationDepths.Y && penetrationDepths.X < penetrationDepths.Z) { contact.Normal = localClosestPoint.X > 0 ? Toolbox.RightVector : Toolbox.LeftVector; contact.PenetrationDepth = penetrationDepths.X; } else if (penetrationDepths.Y < penetrationDepths.Z) { contact.Normal = localClosestPoint.Y > 0 ? Toolbox.UpVector : Toolbox.DownVector; contact.PenetrationDepth = penetrationDepths.Y; } else { contact.Normal = localClosestPoint.Z > 0 ? Toolbox.BackVector : Toolbox.ForwardVector; contact.PenetrationDepth = penetrationDepths.X; } contact.PenetrationDepth += sphere.collisionMargin; Vector3.Transform(ref contact.Normal, ref boxTransform.Orientation, out contact.Normal); } return true; }
/// <summary> /// Create new StaticCollider from existing collision data<para/> /// Создание нового коллайдера из существующих данных /// </summary> /// <param name="colmesh">Collision data<para/>Данные о коллизиях</param> public StaticCollider(CollisionFile.Group colmesh, Vector3 position, Quaternion angles, Vector3 scale) { // Create base transformation matrix // Создание базовой матрицы трансформации Matrix4 mat = Matrix4.CreateScale(scale) * Matrix4.CreateFromQuaternion(angles) * Matrix4.CreateTranslation(position); // Create bodies // Создание тел List<CollisionEntry> col = new List<CollisionEntry>(); // Spheres // Сферы if (colmesh.Spheres!=null) { foreach (CollisionFile.Sphere s in colmesh.Spheres) { // Transforming positions to world coordinates // Трансформация расположения в мировые координаты Vector3 pos = Vector3.TransformPosition(s.Center, mat); float radius = Vector3.TransformVector(Vector3.UnitX * s.Radius, mat).Length; // Create primitive // Создание примитива EntityShape shape = new SphereShape(radius); col.Add(new CollisionEntry() { Type = PrimitiveType.Sphere, Position = pos, Rotation = Quaternion.Identity, Shape = shape, Body = new Entity(shape) }); } } // Cubes // Кубы if (colmesh.Boxes!=null) { foreach (CollisionFile.Box b in colmesh.Boxes) { // Transforming positions to world coordinates // Трансформация расположения в мировые координаты Vector3 pos = Vector3.TransformPosition( new Vector3( (b.Min.X+b.Max.X)/2f, (b.Min.Y+b.Max.Y)/2f, (b.Min.Z+b.Max.Z)/2f ) , mat); float factor = Vector3.TransformVector(Vector3.UnitX, mat).Length; // Create primitive // Создание примитива EntityShape shape = new BoxShape( (float)Math.Abs(b.Max.X-b.Min.X) * factor, (float)Math.Abs(b.Max.Y-b.Min.Y) * factor, (float)Math.Abs(b.Max.Z-b.Min.Z) * factor ); col.Add(new CollisionEntry() { Type = PrimitiveType.Box, Position = pos, Rotation = angles, Shape = shape, Body = new Entity(shape) }); } } // Trimeshes // Тримеши if (colmesh.Meshes!=null) { // Creating vertices array // Создание массива вершин BEPUutilities.Vector3[] verts = new BEPUutilities.Vector3[colmesh.Vertices.Length]; for (int i = 0; i < colmesh.Vertices.Length; i++) { verts[i] = new BEPUutilities.Vector3( colmesh.Vertices[i].X, colmesh.Vertices[i].Y, colmesh.Vertices[i].Z ); } foreach (CollisionFile.Trimesh m in colmesh.Meshes) { // Creating affine transformation // Создание трансформации BEPUutilities.AffineTransform transform = new BEPUutilities.AffineTransform( new BEPUutilities.Vector3(scale.X, scale.Y, scale.Z), new BEPUutilities.Quaternion(angles.X, angles.Y, angles.Z, angles.W), new BEPUutilities.Vector3(position.X, position.Y, position.Z) ); // Create primitive // Создание примитива col.Add(new CollisionEntry() { Type = PrimitiveType.Mesh, Mesh = new StaticMesh(verts, m.Indices, transform) }); } } subColliders = col.ToArray(); }
public CollisionResult CuboidLineTrace(Location halfsize, Location start, Location end, Func<BroadPhaseEntry, bool> filter = null) { BoxShape shape = new BoxShape((double)halfsize.X * 2f, (double)halfsize.Y * 2f, (double)halfsize.Z * 2f); return CuboidLineTrace(shape, start, end, filter); }
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 void PreHandleSpawn() { model = TheClient.Models.GetModel(mod); model.LoadSkin(TheClient.Textures); int ignoreme; if (mode == ModelCollisionMode.PRECISE) { Shape = TheClient.Models.Handler.MeshToBepu(model.Original, out ignoreme); } else if (mode == ModelCollisionMode.CONVEXHULL) { Shape = TheClient.Models.Handler.MeshToBepuConvex(model.Original, out ignoreme); } else if (mode == ModelCollisionMode.AABB) { List<BEPUutilities.Vector3> vecs = TheClient.Models.Handler.GetCollisionVertices(model.Original); Location zero = new Location(vecs[0]); AABB abox = new AABB() { Min = zero, Max = zero }; for (int v = 1; v < vecs.Count; v++) { abox.Include(new Location(vecs[v])); } Location size = abox.Max - abox.Min; Location center = abox.Max - size / 2; Shape = new BoxShape((float)size.X * (float)scale.X, (float)size.Y * (float)scale.Y, (float)size.Z * (float)scale.Z); Offset = -center; } else { List<BEPUutilities.Vector3> vecs = TheClient.Models.Handler.GetCollisionVertices(model.Original); // Location zero = new Location(vecs[0].X, vecs[0].Y, vecs[0].Z); double distSq = 0; for (int v = 1; v < vecs.Count; v++) { if (vecs[v].LengthSquared() > distSq) { distSq = vecs[v].LengthSquared(); } } double size = Math.Sqrt(distSq); Offset = Location.Zero; Shape = new SphereShape((float)size * (float)scale.X); } }
public override void SpawnBody() { Model smod = TheServer.Models.GetModel(model); if (smod == null) // TODO: smod should return a cube when all else fails? { // TODO: Make it safe to -> TheRegion.DespawnEntity(this); return; } Model3D smodel = smod.Original; if (smodel == null) // TODO: smodel should return a cube when all else fails? { // TODO: Make it safe to -> TheRegion.DespawnEntity(this); return; } if (mode == ModelCollisionMode.PRECISE) { Shape = TheServer.Models.handler.MeshToBepu(smodel, out modelVerts); // TODO: Scale! } if (mode == ModelCollisionMode.CONVEXHULL) { Shape = TheServer.Models.handler.MeshToBepuConvex(smodel, out modelVerts); // TODO: Scale! } else if (mode == ModelCollisionMode.AABB) { List<BEPUutilities.Vector3> vecs = TheServer.Models.handler.GetCollisionVertices(smodel); Location zero = new Location(vecs[0]); AABB abox = new AABB() { Min = zero, Max = zero }; for (int v = 1; v < vecs.Count; v++) { abox.Include(new Location(vecs[v])); } Location size = abox.Max - abox.Min; Location center = abox.Max - size / 2; offset = -center; Shape = new BoxShape((double)size.X * (double)scale.X, (double)size.Y * (double)scale.Y, (double)size.Z * (double)scale.Z); } else { List<BEPUutilities.Vector3> vecs = TheServer.Models.handler.GetCollisionVertices(smodel); double distSq = 0; for (int v = 1; v < vecs.Count; v++) { if (vecs[v].LengthSquared() > distSq) { distSq = vecs[v].LengthSquared(); } } double size = Math.Sqrt(distSq); offset = Location.Zero; Shape = new SphereShape((double)size * (double)scale.X); } base.SpawnBody(); if (mode == ModelCollisionMode.PRECISE) { offset = InternalOffset; } }