Convex shape with width, length, and height.
Inheritance: ConvexShape
Beispiel #1
0
 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);
 }
Beispiel #2
0
 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;
 }
Beispiel #3
0
 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);
 }
Beispiel #4
0
 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);
        }
Beispiel #6
0
 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;
 }
Beispiel #7
0
        /// <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;
        }
Beispiel #9
0
        ///<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;
        }
Beispiel #10
0
		/// <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();
		}
Beispiel #11
0
 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);
 }
Beispiel #12
0
 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;
     }
 }
Beispiel #13
0
 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);
     }
 }
Beispiel #14
0
 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;
     }
 }