protected override void CreatePhysicsBody() { PhysicsObject po = physicsObject; po.SetCreateProperty(1.0f, po.Elasticity, po.StaticRoughness, po.DynamicRoughness); int splitNum = 10; Box[] boxes = new Box[splitNum]; // 頂点の大きさがゼロにならないよう // 頂点少し下を基準にする float height = size.Y - 1; float splitHeight = height / splitNum; float positionY = splitHeight / 2; for (int i = 0; i < boxes.Length; i++) { // 底辺:高さ = 頂点からの高さ:length という式を // 解いてXとZの長さを算出する float topDownward = size.Y - (splitHeight * (i + 1)); float lengthX = (topDownward * size.X) / size.Y; float lengthZ = (topDownward * size.Z) / size.Y; Vector3 position = new Vector3(-lengthX / 2, positionY, -lengthZ / 2); Vector3 length = new Vector3(lengthX, splitHeight, lengthZ); boxes[i] = new Box(position, Matrix.Identity, length); positionY += splitHeight; } po.CreateBoxes(Vector3.Zero, Matrix.Identity, boxes); }
public override void Initialise() { base.Initialise(); // Create new bodey and collision skin m_Body = new Body(); m_Skin = new CollisionSkin(m_Body); if (m_Body != null) { // Set skin to the body m_Body.CollisionSkin = m_Skin; // Check the skin was successfully created and add this // custom dice as a primitive to the collision skin if (m_Skin != null) { Box box = new Box(Vector3.Zero, Matrix.Identity, transform.Scale); m_Skin.AddPrimitive(box, (int)MaterialTable.MaterialID.BouncyNormal); // Set mass m_Mass = SetMass(1.0f); // Move the body to correct position initially m_Body.MoveTo(transform.Position, Matrix.Identity); // Apply transform to skin m_Skin.ApplyLocalTransform(new JigLibX.Math.Transform(-m_Mass, Matrix.Identity)); // Enable body EnableBody(); } } }
public BowlingPin(Game game, Model model, Matrix orientation, Vector3 position) : base(game, model) { body = new Body(); collision = new CollisionSkin(body); // add a capsule for the main corpus Primitive capsule = new Capsule(Vector3.Zero, Matrix.Identity, 0.1f, 1.3f); // add a small box at the buttom Primitive box = new Box(new Vector3(-0.1f,-0.1f,-0.1f), Matrix.Identity, Vector3.One * 0.2f); // add a sphere in the middle Primitive sphere = new Sphere(new Vector3(0.0f, 0.0f, 0.3f), 0.3f); collision.AddPrimitive(capsule, new MaterialProperties(0.1f, 0.5f, 0.5f)); collision.AddPrimitive(box, new MaterialProperties(0.1f, 0.5f, 0.5f)); collision.AddPrimitive(sphere, new MaterialProperties(0.1f, 0.5f, 0.5f)); body.CollisionSkin = this.collision; Vector3 com = SetMass(0.5f); body.MoveTo(position, orientation); collision.ApplyLocalTransform(new Transform(-com, Matrix.Identity)); body.EnableBody(); this.scale = Vector3.One * 10.0f; }
public BoxActor(Game game, Vector3 position, Vector3 scale) : base(game) { this.position = position; this.scale = scale; this.Body = new Body(); this.Skin = new CollisionSkin(this.Body); this.Body.CollisionSkin = this.Skin; Box box = new Box(Vector3.Zero, Matrix.Identity, scale); this.Skin.AddPrimitive(box, new MaterialProperties( 0.8f, // elasticity 0.8f, // static roughness 0.7f // dynamic roughness )); Vector3 com = SetMass(1.0f); this.Body.MoveTo(this.position, Matrix.Identity); this.Skin.ApplyLocalTransform(new Transform(-com, Matrix.Identity)); this.Body.EnableBody(); }
public Missile(ParentGame game, Model modelObj, Texture2D[] modelTextures, DrawingClass drawClass, GameplayScreen Screen) : base(game, modelObj, modelTextures) { this.drawClass = drawClass; this.Screen = Screen; _body = new Body(); _skin = new CollisionSkin(_body); _body.CollisionSkin = _skin; Box box = new Box(Vector3.Zero, Matrix.Identity, new Vector3(1f,1f,4f)); _skin.AddPrimitive(box, new MaterialProperties(0.8f, 0.8f, 0.7f)); Vector3 com = SetMass(2.0f); _body.MoveTo(position, Matrix.Identity); _skin.ApplyLocalTransform(new Transform(-com, Matrix.Identity)); _body.EnableBody(); Body.ExternalData = this; Vector3 pos = position; Vector3 forwardVec = Body.Orientation.Forward; forwardVec.Normalize(); pos -= forwardVec * 10; // Use the particle emitter helper to output our trail particles. trailEmitter = new ParticleEmitter(drawClass.projectileTrailParticles, trailParticlesPerSecond, position); rgob = new RagdollObject(parentGame, null, null, null, RagdollObject.RagdollType.Simple, 1.0f, 3); rgob.Position = position; //rgob.PutToSleep(); //rgob.limbs[0].PhysicsBody.AngularVelocity = (new Vector3(1, 1, 0) * 2000); RagdollTransforms = new List<Matrix>(); RagdollTransforms = rgob.GetWorldMatrix(); foreach (JigLibX.Objects.PhysicObject lim in rgob.limbs) DisableCollisions(lim.PhysicsBody, Body); foreach (JigLibX.Objects.PhysicObject lim in rgob.limbs) foreach (BuildingPiece pic in Screen.PieceList) DisableCollisions(lim.PhysicsBody, pic.Body); foreach (JigLibX.Objects.PhysicObject lim in rgob.limbs) foreach (Building bld in Screen.Buildings) DisableCollisions(lim.PhysicsBody, bld.Body); foreach (JigLibX.Objects.PhysicObject lim in rgob.limbs) DisableCollisions(lim.PhysicsBody, Screen.terrainActor.Body); foreach (JigLibX.Objects.PhysicObject limb0 in rgob.limbs) foreach (Missile mis in Screen.BulletList) foreach (JigLibX.Objects.PhysicObject limb1 in mis.rgob.limbs) DisableCollisions(limb1.PhysicsBody, limb0.PhysicsBody); }
public override void SetDims(Vector3 min, Vector3 max) { dimsMin = min; dimsMax = max; Vector3 sides = max - min; Box box1 = new Box(min, Matrix.Identity, sides); collisionSkin.RemoveAllPrimitives(); collisionSkin.AddPrimitive(box1, new MaterialProperties(0.3f, 0.5f, 0.3f)); body.Vehicle.SetupDefaultWheels(); }
public CylinderObject(Game game, float radius, float length, Vector3 position, Model model) : base(game, model) { body = new Body(); collision = new CollisionSkin(body); if (length - 2.0f * radius < 0.0f) throw new ArgumentException("Radius must be at least half length"); Capsule middle = new Capsule(Vector3.Zero, Matrix.Identity, radius, length - 2.0f * radius); float sideLength = 2.0f * radius / (float) Math.Sqrt(2.0d); Vector3 sides = new Vector3(-0.5f * sideLength, -0.5f * sideLength, -radius); Box supply0 = new Box(sides, Matrix.Identity, new Vector3(sideLength, sideLength, length)); Box supply1 = new Box(Vector3.Transform(sides,Matrix.CreateRotationZ(MathHelper.PiOver4)), Matrix.CreateRotationZ(MathHelper.PiOver4), new Vector3(sideLength, sideLength, length)); collision.AddPrimitive(middle, new MaterialProperties(0.8f, 0.8f, 0.7f)); collision.AddPrimitive(supply0, new MaterialProperties(0.8f, 0.8f, 0.7f)); collision.AddPrimitive(supply1, new MaterialProperties(0.8f, 0.8f, 0.7f)); body.CollisionSkin = this.collision; Vector3 com = SetMass(1.0f); collision.ApplyLocalTransform(new Transform(-com, Matrix.Identity)); #region Manually set body inertia float cylinderMass = body.Mass; float comOffs = (length - 2.0f * radius) * 0.5f; ; float Ixx = 0.5f * cylinderMass * radius * radius + cylinderMass * comOffs * comOffs; float Iyy = 0.25f * cylinderMass * radius * radius + (1.0f / 12.0f) * cylinderMass * length * length + cylinderMass * comOffs * comOffs; float Izz = Iyy; body.SetBodyInertia(Ixx, Iyy, Izz); #endregion body.MoveTo(position, Matrix.CreateRotationX(MathHelper.PiOver2)); body.EnableBody(); this.scale = new Vector3(radius, radius, length * 0.5f); }
public Cuboid(Vector dimension) { Dimension = dimension; PhysicsBody = new Body(); collisionSkin = new CollisionSkin(PhysicsBody); PhysicsBody.CollisionSkin = collisionSkin; var box = new Box(Vector3.Zero, Microsoft.Xna.Framework.Matrix.Identity, Dimension.ToXna()); collisionSkin.AddPrimitive(box, new MaterialProperties(0.1f, 0.4f, 0.9f)); var com = ApplyMass(1.0f); // PhysicsBody.MoveTo(Utils.VectorBalderToXna(this.Position), Microsoft.Xna.Framework.Matrix.Identity); collisionSkin.ApplyLocalTransform(new JigLibX.Math.Transform(-com, Microsoft.Xna.Framework.Matrix.Identity)); PhysicsBody.EnableBody(); }
public BuildingPiece(ParentGame game, Model modelObj, Texture2D[] modelTextures, DrawingClass drawClass, GameplayScreen Screen, float Length, float Width, float Height) : base(game, modelObj, modelTextures) { // Use the particle emitter helper to output our trail particles. trailEmitter = new ParticleEmitter(drawClass.smokePlumeParticles, 3, position); fireEmitter = new ParticleEmitter(drawClass.fireParticles, 30, position); this.Screen = Screen; this.drawClass = drawClass; _body = new Body(); _skin = new CollisionSkin(_body); _body.CollisionSkin = _skin; //Box box = new Box(Vector3.Zero, Matrix.Identity, new Vector3(10f, 7f, 7f)); Box box = new Box(Vector3.Zero, Matrix.Identity, new Vector3(Length, Width, Height)); if (Length > Width && Length > Height) boundSphere.Radius = Length; else if (Width > Length && Width > Height) boundSphere.Radius = Width; else boundSphere.Radius = Height; _skin.AddPrimitive(box, new MaterialProperties(0.8f, 0.8f, 0.7f)); Vector3 com = SetMass(3.0f); _body.MoveTo(position, Matrix.Identity); _skin.ApplyLocalTransform(new Transform(-com, Matrix.Identity)); _body.EnableBody(); Body.ExternalData = this; SetBody(rotation); Body.AllowFreezing = true; Body.SetDeactivationTime(1); foreach (BuildingPiece pic in Screen.PieceList) DisableCollisions(this.Body, pic.Body); foreach (Building bld in Screen.Buildings) DisableCollisions(this.Body, bld.Body); }
static Body CreateCube(Vector3 pos, Vector3 size) { Body _body = new Body(); CollisionSkin _skin = new CollisionSkin(_body); _body.CollisionSkin = _skin; Box box = new Box(pos, Matrix4.Identity, size); _skin.AddPrimitive(box, new MaterialProperties(0.8f, 0.8f, 0.7f)); Vector3 com = SetMass(1.0f, _skin, _body); _body.MoveTo(pos, Matrix4.Identity); _skin.ApplyLocalTransform(new Transform(-com, Matrix4.Identity)); _body.EnableBody(); return(_body); }
public BoxActor(Game game, Vector3 position, Vector3 scale) : base(game) { this.position = position; this.scale = scale; _body = new Body(); _skin = new CollisionSkin(_body); _body.CollisionSkin = _skin; Box box = new Box(Vector3.Zero, Matrix.Identity, scale); _skin.AddPrimitive(box, new MaterialProperties(0.8f, 0.8f, 0.7f)); Vector3 com = SetMass(1.0f); _body.MoveTo(position, Matrix.Identity); _skin.ApplyLocalTransform(new JigLibX.Math.Transform(-com, Matrix.Identity)); _body.EnableBody(); }
protected override void LoadSpecific() { base.LoadSpecific(); // Create new bodey and collision skin m_Body = new Body(); m_Skin = new CollisionSkin(m_Body); if (m_Body != null) { // Set skin to the body m_Body.CollisionSkin = m_Skin; // Check the skin was successfully created and add this // custom dice as a primitive to the collision skin if (m_Skin != null) { Vector3 sideLengths = (m_BoundingBox.Max - m_BoundingBox.Min); if (sideLengths.Y <= 0) sideLengths.Y = 0.1f; Matrix rotMat = Matrix.CreateFromQuaternion(transform.Rotation); Box box = new Box(Vector3.Zero, Matrix.Identity, sideLengths); m_Skin.AddPrimitive(box, (int)MaterialTable.MaterialID.BouncyNormal); // Set mass m_Mass = SetMass(1.0f); // Move the body to correct position initially m_Body.MoveTo(transform.Position, Matrix.Identity); // Apply transform to skin m_Skin.ApplyLocalTransform(new JigLibX.Math.Transform(-m_Mass, Matrix.Identity)); // Enable it Enable(); // Set to immovable m_Body.Immovable = true; } } }
public Block(BlockSimulatorGame game, Vector3 position, Vector3 scale, string modelDir) : base(game, position, scale, modelDir) { Box box = new Box(Position, Matrix.Identity, Scale); Skin.AddPrimitive(box, new MaterialProperties( 0.8f, // elasticity 0.8f, // static roughness 0.7f // dynamic roughness )); Vector3 com = SetMass(1.0f); Body.MoveTo(Position, Matrix.Identity); Skin.ApplyLocalTransform(new Transform(-com, Matrix.Identity)); Body.EnableBody(); PhysicsSystem.CurrentPhysicsSystem.AddBody(Body); LoadContent(game, modelDir); }
// Sets up the collision skin void SetupSkin(float length, float radius) { if (length - 2.0f * radius < 0.0f) throw new ArgumentException("Radius must be at least half length"); this.length = length; this.radius = radius; Capsule middle = new Capsule(Vector3.Zero, Matrix.Identity, radius, length - 2.0f * radius); float sideLength = 2.0f * radius / (float)Math.Sqrt(2.0d); Vector3 sides = new Vector3(-0.5f * sideLength, -0.5f * sideLength, -radius); Box supply0 = new Box(sides, Matrix.Identity, new Vector3(sideLength, sideLength, length)); Box supply1 = new Box(Vector3.Transform(sides, Matrix.CreateRotationZ(MathHelper.PiOver4)), Matrix.CreateRotationZ(MathHelper.PiOver4), new Vector3(sideLength, sideLength, length)); CollisionSkin.AddPrimitive(middle, new MaterialProperties(0.8f, 0.8f, 0.7f)); CollisionSkin.AddPrimitive(supply0, new MaterialProperties(0.8f, 0.8f, 0.7f)); CollisionSkin.AddPrimitive(supply1, new MaterialProperties(0.8f, 0.8f, 0.7f)); }
protected override void CreatePhysicsBody() { PhysicsObject po = physicsObject; po.SetCreateProperty(1.0f, po.Elasticity, po.StaticRoughness, po.DynamicRoughness); float chipSize = size.X / 5; Vector3 pillarLength = new Vector3(chipSize, size.Y, size.Z); Vector3 leftPosition = new Vector3(0, 0, 0); Vector3 rightPosition = new Vector3(chipSize * 4, 0, 0); Vector3 topBarLength = new Vector3(chipSize * 3, chipSize, size.Z); Vector3 topPosition = new Vector3(chipSize, size.Y - chipSize, 0); Box leftPillar = new Box(leftPosition, Matrix.Identity, pillarLength); Box rightPillar = new Box(rightPosition, Matrix.Identity, pillarLength); Box TopBar = new Box(topPosition, Matrix.Identity, topBarLength); Box[] boxes = { leftPillar, rightPillar, TopBar }; po.CreateBoxes(Vector3.Zero, Matrix.Identity, boxes); }
public TestObject(Game game,Model model) : base(game,model) { body = new Body(); collision = new CollisionSkin(body); Box boxMiddle = new Box(new Vector3(-3, 0 ,-0.5f), Matrix.Identity, new Vector3(6,1,1)); Box boxLeft = new Box(new Vector3(-3, -3f, -0.5f), Matrix.Identity, new Vector3(1, 4, 1)); Box boxRight = new Box(new Vector3(2, -3f, -0.5f), Matrix.Identity, new Vector3(1, 4, 1)); collision.AddPrimitive(boxMiddle, new MaterialProperties(0.2f, 0.7f, 0.6f)); collision.AddPrimitive(boxLeft, new MaterialProperties(0.2f, 0.7f, 0.6f)); collision.AddPrimitive(boxRight, new MaterialProperties(0.2f, 0.7f, 0.6f)); body.CollisionSkin = this.collision; Vector3 com = SetMass(1.0f); // collision.ApplyLocalTransform(new Transform(-com, Matrix.Identity)); body.MoveTo(Vector3.Up * 10, Matrix.Identity); //body.Immovable = true; body.EnableBody(); }
public virtual void Initialize() { _body = new Body(); _skin = new CollisionSkin(_body); _body.CollisionSkin = _skin; // l w h //Box box = new Box(Vector3.Zero, Matrix.Identity, new Vector3(9f, 9f, 39f)); //if (Type == "DEPOT") // box = new Box(Vector3.Zero, Matrix.Identity, new Vector3(20, 15, 11f)); Box box = new Box(Vector3.Zero, Matrix.Identity, new Vector3(9f, 39f, 9f)); boundSphere.Radius = 39; if (Type == "DEPOT") { box = new Box(Vector3.Zero, Matrix.Identity, new Vector3(20, 11, 15f)); boundSphere.Radius = 20; } _skin.AddPrimitive(box, new MaterialProperties(1, 1, 1)); Vector3 com = SetMass(1); //_body.MoveTo(position, Matrix.Identity); _skin.ApplyLocalTransform(new Transform(-com, Matrix.Identity)); _body.EnableBody(); Body.ExternalData = this; SetBody(rotation); DisableCollisions(Screen.terrainActor.Body, Body); }
/// <summary> /// CollDetectBoxStaticMeshOverlap /// </summary> /// <param name="oldBox"></param> /// <param name="newBox"></param> /// <param name="mesh"></param> /// <param name="info"></param> /// <param name="collTolerance"></param> /// <param name="collisionFunctor"></param> /// <returns>bool</returns> private static bool CollDetectBoxStaticMeshOverlap(Box oldBox, Box newBox, TriangleMesh mesh, ref CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor) { float boxRadius = newBox.GetBoundingRadiusAroundCentre(); #region REFERENCE: Vector3 boxCentre = newBox.GetCentre(); Vector3 boxCentre; newBox.GetCentre(out boxCentre); // Deano need to trasnform the box center into mesh space Matrix4 invTransformMatrix = mesh.InverseTransformMatrix; Vector3.Transform(ref boxCentre, ref invTransformMatrix, out boxCentre); #endregion BoundingBox bb = BoundingBoxHelper.InitialBox; BoundingBoxHelper.AddBox(newBox, ref bb); unsafe { bool collision = false; #if USE_STACKALLOC int* potentialTriangles = stackalloc int[MaxLocalStackTris]; { #else int[] potTriArray = IntStackAlloc(); fixed( int* potentialTriangles = potTriArray) { #endif // aabox is done in mesh space and handles the mesh transform correctly int numTriangles = mesh.GetTrianglesIntersectingtAABox(potentialTriangles, MaxLocalStackTris, ref bb); for (int iTriangle = 0; iTriangle < numTriangles; ++iTriangle) { IndexedTriangle meshTriangle = mesh.GetTriangle(potentialTriangles[iTriangle]); // quick early test is done in mesh space float dist = meshTriangle.Plane.DotCoordinate(boxCentre); // BEN-BUG-FIX: Fixed by chaning 0.0F to -boxRadius. if (dist > boxRadius || dist < -boxRadius) continue; if (DoOverlapBoxTriangleTest( oldBox, newBox, ref meshTriangle, mesh, ref info, collTolerance, collisionFunctor)) { collision = true; } } #if USE_STACKALLOC } #else } FreeStackAlloc(potTriArray); #endif return collision; } }
/// <summary> /// CollDetectSweep /// </summary> /// <param name="info"></param> /// <param name="collTolerance"></param> /// <param name="collisionFunctor"></param> private void CollDetectSweep(ref CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor) { // todo - proper swept test // note - mesh is static and its triangles are in world space TriangleMesh mesh = info.Skin1.GetPrimitiveNewWorld(info.IndexPrim1) as TriangleMesh; Box oldBox = info.Skin0.GetPrimitiveOldWorld(info.IndexPrim0) as Box; Box newBox = info.Skin0.GetPrimitiveNewWorld(info.IndexPrim0) as Box; Vector3 oldCentre; oldBox.GetCentre(out oldCentre); Vector3 newCentre; newBox.GetCentre(out newCentre); Vector3 delta; Vector3.Subtract(ref newCentre, ref oldCentre, out delta); float boxMinLen = 0.5f * System.Math.Min(newBox.SideLengths.X, System.Math.Min(newBox.SideLengths.Y, newBox.SideLengths.Z)); int nPositions = 1 + (int)(delta.Length / boxMinLen); // limit the max positions... if (nPositions > 50) { System.Diagnostics.Debug.WriteLine("Warning - clamping max positions in swept box test"); nPositions = 50; } if (nPositions == 1) { CollDetectBoxStaticMeshOverlap(oldBox, newBox, mesh,ref info, collTolerance, collisionFunctor); } else { BoundingBox bb = BoundingBoxHelper.InitialBox; BoundingBoxHelper.AddBox(oldBox, ref bb); BoundingBoxHelper.AddBox(newBox, ref bb); unsafe { #if USE_STACKALLOC int* potentialTriangles = stackalloc int[MaxLocalStackTris]; { #else int[] potTriArray = IntStackAlloc(); fixed( int* potentialTriangles = potTriArray) { #endif int numTriangles = mesh.GetTrianglesIntersectingtAABox(potentialTriangles, MaxLocalStackTris, ref bb); if (numTriangles > 0) { for (int i = 0; i <= nPositions; ++i) { float frac = ((float)i) / nPositions; Vector3 centre; Vector3.Multiply(ref delta, frac, out centre); Vector3.Add(ref centre, ref oldCentre, out centre); Matrix4 orient = Matrix4Extensions.Add(Matrix4Extensions.Multiply(oldBox.Orientation, 1.0f - frac), Matrix4Extensions.Multiply(newBox.Orientation, frac)); Box box = new Box(centre - 0.5f * Vector3Extensions.TransformNormal(newBox.SideLengths, orient), orient, newBox.SideLengths); // ideally we'd break if we get one collision... but that stops us getting multiple collisions // when we enter a corner (two walls meeting) - can let us pass through CollDetectBoxStaticMeshOverlap(oldBox, box, mesh, ref info, collTolerance, collisionFunctor); } } #if USE_STACKALLOC } #else } FreeStackAlloc(potTriArray); #endif } } }
/// <summary> /// GetBoxTriangleIntersectionPoints /// Pushes intersection points onto the back of pts. Returns the /// number of points found. /// Points that are close together (compared to /// combinationDistance) get combined /// </summary> /// <param name="pts"></param> /// <param name="box"></param> /// <param name="triangle"></param> /// <param name="combinationDistance"></param> /// <returns>int</returns> private static int GetBoxTriangleIntersectionPoints(List<Vector3> pts, Box box, Triangle triangle, float combinationDistance) { // first intersect each edge of the box with the triangle Box.Edge[] edges; box.GetEdges(out edges); Vector3[] boxPts; box.GetCornerPoints(out boxPts); float tS; float tv1, tv2; // BEN-OPTIMISATION: Allocating just one Vector3 to be reused. Vector3 point = new Vector3(); int iEdge; for (iEdge = 0; iEdge < 12; ++iEdge) { Box.Edge edge = edges[iEdge]; Segment seg = new Segment(boxPts[(int)edge.Ind0], boxPts[(int)edge.Ind1] - boxPts[(int)edge.Ind0]); if (Intersection.SegmentTriangleIntersection(out tS, out tv1, out tv2, seg, triangle)) { // BEN-OPTIMISATION: Reusing the existing point variable instead allocating new ones. // This also allows point to be based by reference. seg.GetPoint(ref point, tS); AddPoint(pts, ref point, combinationDistance * combinationDistance); } } Vector3 pos, n; // now each edge of the triangle with the box for (iEdge = 0; iEdge < 3; ++iEdge) { #region "BEN-OPTIMISATION: Remove excess allocations and pass variables by reference." // ORIGINAL CODE: /*Vector3 pt0 = triangle.GetPoint(iEdge); Vector3 pt1 = triangle.GetPoint((iEdge + 1) % 3); Segment s1 = new Segment(pt0, pt1 - pt0); Segment s2 = new Segment(pt1, pt0 - pt1);*/ // OPTIMISED CODE: Vector3 pt0 = triangle.GetPoint(iEdge); Vector3 pt1 = triangle.GetPoint((iEdge + 1) % 3); Vector3 difference1; Vector3 difference2; Vector3.Subtract(ref pt1, ref pt0, out difference1); Vector3.Subtract(ref pt0, ref pt1, out difference2); Segment s1 = new Segment(ref pt0, ref difference1); Segment s2 = new Segment(ref pt1, ref difference2); #endregion if (box.SegmentIntersect(out tS, out pos, out n, s1)) AddPoint(pts, ref pos, combinationDistance * combinationDistance); if (box.SegmentIntersect(out tS, out pos, out n, s2)) AddPoint(pts, ref pos, combinationDistance * combinationDistance); } return pts.Count; }
/// <summary> /// DoOverlapBoxTriangleTest /// </summary> /// <param name="oldBox"></param> /// <param name="newBox"></param> /// <param name="triangle"></param> /// <param name="mesh"></param> /// <param name="info"></param> /// <param name="collTolerance"></param> /// <param name="collisionFunctor"></param> /// <returns>bool</returns> private static bool DoOverlapBoxTriangleTest(Box oldBox, Box newBox, ref IndexedTriangle triangle, TriangleMesh mesh, ref CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor) { Matrix4 dirs0 = newBox.Orientation; #region REFERENCE: Triangle tri = new Triangle(mesh.GetVertex(triangle.GetVertexIndex(0)),mesh.GetVertex(triangle.GetVertexIndex(1)),mesh.GetVertex(triangle.GetVertexIndex(2))); Vector3 triVec0; Vector3 triVec1; Vector3 triVec2; mesh.GetVertex(triangle.GetVertexIndex(0), out triVec0); mesh.GetVertex(triangle.GetVertexIndex(1), out triVec1); mesh.GetVertex(triangle.GetVertexIndex(2), out triVec2); // Deano move tri into world space Matrix4 transformMatrix = mesh.TransformMatrix; Vector3.Transform(ref triVec0, ref transformMatrix, out triVec0); Vector3.Transform(ref triVec1, ref transformMatrix, out triVec1); Vector3.Transform(ref triVec2, ref transformMatrix, out triVec2); Triangle tri = new Triangle(ref triVec0,ref triVec1,ref triVec2); #endregion #region REFERENCE Vector3 triEdge0 = (tri.GetPoint(1) - tri.GetPoint(0)); Vector3 pt0; Vector3 pt1; tri.GetPoint(0, out pt0); tri.GetPoint(1, out pt1); Vector3 triEdge0; Vector3.Subtract(ref pt1, ref pt0, out triEdge0); #endregion #region REFERENCE Vector3 triEdge1 = (tri.GetPoint(2) - tri.GetPoint(1)); Vector3 pt2; tri.GetPoint(2, out pt2); Vector3 triEdge1; Vector3.Subtract(ref pt2, ref pt1, out triEdge1); #endregion #region REFERENCE Vector3 triEdge2 = (tri.GetPoint(0) - tri.GetPoint(2)); Vector3 triEdge2; Vector3.Subtract(ref pt0, ref pt2, out triEdge2); #endregion triEdge0.Normalize(); triEdge1.Normalize(); triEdge2.Normalize(); // BEN-OPTIMISATION: Replaced loops with code that requires no looping. // The new code is faster, has less allocations and math especially // since the method returns as soon as it finds a non-overlapping axis, // i.e. Before irreleveat allocations occur. #region "Old (less efficient) code" /*Vector3 triNormal = triangle.Plane.Normal; // the 15 potential separating axes const int numAxes = 13; Vector3[] axes = new Vector3[numAxes]; axes[0] = triNormal; axes[1] = dirs0.Right; axes[2] = dirs0.Up; axes[3] = dirs0.Backward; Vector3.Cross(ref axes[1], ref triEdge0, out axes[4]); Vector3.Cross(ref axes[1], ref triEdge1, out axes[5]); Vector3.Cross(ref axes[1], ref triEdge2, out axes[6]); Vector3.Cross(ref axes[2], ref triEdge0, out axes[7]); Vector3.Cross(ref axes[2], ref triEdge1, out axes[8]); Vector3.Cross(ref axes[2], ref triEdge2, out axes[9]); Vector3.Cross(ref axes[3], ref triEdge0, out axes[10]); Vector3.Cross(ref axes[3], ref triEdge1, out axes[11]); Vector3.Cross(ref axes[3], ref triEdge2, out axes[12]); // the overlap depths along each axis float[] overlapDepths = new float[numAxes]; // see if the boxes are separate along any axis, and if not keep a // record of the depths along each axis int i; for (i = 0; i < numAxes; ++i) { overlapDepths[i] = 1.0f; if (Disjoint(out overlapDepths[i], axes[i], newBox, tri, collTolerance)) return false; } // The box overlap, find the separation depth closest to 0. float minDepth = float.MaxValue; int minAxis = -1; for (i = 0; i < numAxes; ++i) { // If we can't normalise the axis, skip it float l2 = axes[i].LengthSquared; if (l2 < JiggleMath.Epsilon) continue; // Normalise the separation axis and the depth float invl = 1.0f / (float)System.Math.Sqrt(l2); axes[i] *= invl; overlapDepths[i] *= invl; // If this axis is the minimum, select it if (overlapDepths[i] < minDepth) { minDepth = overlapDepths[i]; minAxis = i; } } if (minAxis == -1) return false; // Make sure the axis is facing towards the 0th box. // if not, invert it Vector3 D = newBox.GetCentre() - tri.Centre; Vector3 N = axes[minAxis]; float depth = overlapDepths[minAxis];*/ #endregion #region "Optimised code" Vector3 triNormal = triangle.Plane.Normal; Vector3 right = dirs0.Right(); Vector3 up = dirs0.Up(); Vector3 backward = dirs0.Backward(); float testDepth; if (Disjoint(out testDepth, ref triNormal, newBox, ref tri, collTolerance)) return (false); float depth = testDepth; Vector3 N = triNormal; if (Disjoint(out testDepth, ref right, newBox, ref tri, collTolerance)) return (false); if (testDepth < depth) { depth = testDepth; N = right; } if (Disjoint(out testDepth, ref up, newBox, ref tri, collTolerance)) return (false); if (testDepth < depth) { depth = testDepth; N = up; } if (Disjoint(out testDepth, ref backward, newBox, ref tri, collTolerance)) return (false); if (testDepth < depth) { depth = testDepth; N = backward; } Vector3 axis; Vector3.Cross(ref right, ref triEdge0, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) return (false); testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref right, ref triEdge1, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) return (false); testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref right, ref triEdge2, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) return (false); testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref up, ref triEdge0, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) return (false); testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref up, ref triEdge1, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) return (false); testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref up, ref triEdge2, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) return (false); testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref backward, ref triEdge0, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) return (false); testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref backward, ref triEdge1, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) return (false); testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref backward, ref triEdge2, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) return (false); testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } /*if (N == Vector3.Zero) return (false);*/ Vector3 D = newBox.GetCentre() - tri.Centre; N.Normalize(); int i; #endregion if (Vector3.Dot(D, N) < 0.0f) N *= -1; Vector3 boxOldPos = (info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero; Vector3 boxNewPos = (info.Skin0.Owner != null) ? info.Skin0.Owner.Position : Vector3.Zero; Vector3 meshPos = (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero; List<Vector3> pts = new List<Vector3>(); //pts.Clear(); const float combinationDist = 0.05f; GetBoxTriangleIntersectionPoints(pts, newBox, tri, depth + combinationDist); // adjust the depth #region REFERENCE: Vector3 delta = boxNewPos - boxOldPos; Vector3 delta; Vector3.Subtract(ref boxNewPos, ref boxOldPos, out delta); #endregion #region REFERENCE: float oldDepth = depth + Vector3.Dot(delta, N); float oldDepth; Vector3.Dot(ref delta, ref N, out oldDepth); oldDepth += depth; #endregion unsafe { // report collisions int numPts = pts.Count; #if USE_STACKALLOC SmallCollPointInfo* collPts = stackalloc SmallCollPointInfo[MaxLocalStackSCPI]; #else SmallCollPointInfo[] collPtArray = SCPIStackAlloc(); fixed (SmallCollPointInfo* collPts = collPtArray) #endif { if (numPts > 0) { if (numPts >= MaxLocalStackSCPI) { numPts = MaxLocalStackSCPI - 1; } // adjust positions for (i = 0; i < numPts; ++i) { // BEN-OPTIMISATION: Reused existing SmallCollPointInfo and inlined vector substraction. collPts[i].R0.X = pts[i].X - boxNewPos.X; collPts[i].R0.Y = pts[i].Y - boxNewPos.Y; collPts[i].R0.Z = pts[i].Z - boxNewPos.Z; collPts[i].R1.X = pts[i].X - meshPos.X; collPts[i].R1.Y = pts[i].Y - meshPos.Y; collPts[i].R1.Z = pts[i].Z - meshPos.Z; collPts[i].InitialPenetration = oldDepth; } collisionFunctor.CollisionNotify(ref info, ref N, collPts, numPts); #if !USE_STACKALLOC FreeStackAlloc(collPtArray); #endif return true; } else { #if !USE_STACKALLOC FreeStackAlloc(collPtArray); #endif return false; } } } }
// BEN-OPTIMISATION: ref axis and ref triangle, BEN-CLEANUP: Renamed min and max variables. /// <summary> /// Disjoint Returns true if disjoint. Returns false if intersecting, /// and sets the overlap depth, d scaled by the axis length /// </summary> /// <param name="d"></param> /// <param name="axis"></param> /// <param name="box"></param> /// <param name="triangle"></param> /// <param name="collTolerance"></param> /// <returns>bool</returns> private static bool Disjoint(out float d, ref Vector3 axis, Box box, ref Triangle triangle, float collTolerance) { float minBox, maxBox, minTri, maxTri; // BEN-OPTIMISATION: ref axis box.GetSpan(out minBox, out maxBox, ref axis); triangle.GetSpan(out minTri, out maxTri, ref axis); if (minBox > (maxTri + collTolerance + JiggleMath.Epsilon) || minTri > (maxBox + collTolerance + JiggleMath.Epsilon)) { d = 0.0f; return (true); } if ((maxBox > maxTri) && (minTri > minBox)) { // triangle is inside - choose the min dist to move it out d = System.Math.Min(maxBox - minTri, maxTri - minBox); } else if ((maxTri > maxBox) && (minBox > minTri)) { // box is inside - choose the min dist to move it out d = System.Math.Min(maxTri - minBox, maxBox - minTri); } else { // objects overlap d = (maxBox < maxTri) ? maxBox : maxTri; d -= (minBox > minTri) ? minBox : minTri; } return (false); }
public Aircraft GetAircraft(Vector3 pos, Model model, Vector3 size, Matrix orient) { Box boxPrimitive = new Box(-.5f * size, orient, size); // relative to the body, the position is the top left-ish corner instead of the center, so subtract from the center, half of all sides to get that point. Box leftWing = new Box(new Vector3(-6, -.6f, -2.30f), orient, new Vector3(5, .1f, 1.2f)); Box rightWing = new Box(new Vector3(.7f, -.6f, -2.30f), orient, new Vector3(5, .1f, 1.2f)); Box fuse = new Box(new Vector3(-.9f, -.7f, -2.30f), orient, new Vector3(1.9f, 1f, 6f)); //leftWing.Position List<MaterialProperties> props = new List<MaterialProperties>(); props.Add(new MaterialProperties(.3f,.3f,.3f)); props.Add(new MaterialProperties(.3f, .3f, .3f)); props.Add(new MaterialProperties(.3f, .3f, .3f)); List<Primitive> prims = new List<Primitive>(); prims.Add(leftWing); prims.Add(rightWing); prims.Add(fuse); Aircraft a = new Aircraft(new Vector3(0, -14, 0), new Vector3(1, 1, 1), prims, props, model, 0); return a; }
public Gobject GetBox(Vector3 pos, Vector3 size, Matrix orient, Model model, bool moveable) { // position of box was upper leftmost corner // body has world position // skin is relative to the body Box boxPrimitive = new Box(-.5f * size, orient, size); // relative to the body, the position is the top left-ish corner instead of the center, so subtract from the center, half of all sides to get that point. Gobject box = new Gobject( pos, size / 2, boxPrimitive, model, moveable, 0 ); return box; }
/// <summary> /// SegmentBoxDistanceSq /// </summary> /// <param name="pfLParam"></param> /// <param name="pfBParam0"></param> /// <param name="pfBParam1"></param> /// <param name="pfBParam2"></param> /// <param name="rkSeg"></param> /// <param name="rkBox"></param> /// <returns>float</returns> public static float SegmentBoxDistanceSq(out float pfLParam, out float pfBParam0, out float pfBParam1, out float pfBParam2, Segment rkSeg, Box rkBox) { pfLParam = pfBParam0 = pfBParam1 = pfBParam2 = 0.0f; Line line = new Line(rkSeg.Origin, rkSeg.Delta); float fLP, fBP0, fBP1, fBP2; float fSqrDistance = SqrDistance(line, rkBox, out fLP, out fBP0, out fBP1, out fBP2); if (fLP >= 0.0f) { if (fLP <= 1.0f) { pfLParam = fLP; pfBParam0 = fBP0;// + 0.5f; pfBParam1 = fBP1;// + 0.5f; pfBParam2 = fBP2;// + 0.5f; return MathHelper.Max(fSqrDistance, 0.0f); } else { fSqrDistance = SqrDistance(rkSeg.Origin + rkSeg.Delta, rkBox, out pfBParam0, out pfBParam1, out pfBParam2); pfLParam = 1.0f; return MathHelper.Max(fSqrDistance, 0.0f); } } else { fSqrDistance = SqrDistance(rkSeg.Origin, rkBox, out pfBParam0, out pfBParam1, out pfBParam2); pfLParam = 0.0f; return MathHelper.Max(fSqrDistance, 0.0f); } }
/// <summary> /// FaceC /// </summary> /// <param name="kPnt"></param> /// <param name="kDir"></param> /// <param name="rkBox"></param> /// <param name="kPmE"></param> /// <param name="pfLParam"></param> /// <param name="sqrDistance"></param> private static void FaceC(ref Vector3 kPnt, Vector3 kDir, Box rkBox, Vector3 kPmE,out float pfLParam, ref float sqrDistance) { // 1,2,0 Vector3 kPpE; float fLSqr, fInv, fTmp, fParam, fT, fDelta; kPpE.Z = kPnt.Z + rkBox.GetHalfSideLengths().Z; kPpE.X = kPnt.X + rkBox.GetHalfSideLengths().X; if (kDir.Y * kPpE.Z >= kDir.Z * kPmE.Y) { if (kDir.Y * kPpE.X >= kDir.X * kPmE.Y) { // v.Z >= -e.Z, v.X >= -e.X (distance = 0) kPnt.Y = rkBox.GetHalfSideLengths().Y; fInv = 1.0f / kDir.Y; kPnt.Z -= kDir.Z * kPmE.Y * fInv; kPnt.X -= kDir.X * kPmE.Y * fInv; pfLParam = -kPmE.Y * fInv; } else { // v.Z >= -e.Z, v.X < -e.X fLSqr = kDir.Y * kDir.Y + kDir.X * kDir.X; fTmp = fLSqr * kPpE.Z - kDir.Z * (kDir.Y * kPmE.Y + kDir.X * kPpE.X); if (fTmp <= 2.0f * fLSqr * rkBox.GetHalfSideLengths().Z) { fT = fTmp / fLSqr; fLSqr += kDir.Z * kDir.Z; fTmp = kPpE.Z - fT; fDelta = kDir.Y * kPmE.Y + kDir.Z * fTmp + kDir.X * kPpE.X; fParam = -fDelta / fLSqr; sqrDistance += kPmE.Y * kPmE.Y + fTmp * fTmp + kPpE.X * kPpE.X + fDelta * fParam; pfLParam = fParam; kPnt.Y = rkBox.GetHalfSideLengths().Y; kPnt.Z = fT - rkBox.GetHalfSideLengths().Z; kPnt.X = -rkBox.GetHalfSideLengths().X; } else { fLSqr += kDir.Z * kDir.Z; fDelta = kDir.Y * kPmE.Y + kDir.Z * kPmE.Z + kDir.X * kPpE.X; fParam = -fDelta / fLSqr; sqrDistance += kPmE.Y * kPmE.Y + kPmE.Z * kPmE.Z + kPpE.X * kPpE.X + fDelta * fParam; pfLParam = fParam; kPnt.Y = rkBox.GetHalfSideLengths().Y; kPnt.Z = rkBox.GetHalfSideLengths().Z; kPnt.X = -rkBox.GetHalfSideLengths().X; } } } else { if (kDir.Y * kPpE.X >= kDir.X * kPmE.Y) { // v.Z < -e.Z, v.X >= -e.X fLSqr = kDir.Y * kDir.Y + kDir.Z * kDir.Z; fTmp = fLSqr * kPpE.X - kDir.X * (kDir.Y * kPmE.Y + kDir.Z * kPpE.Z); if (fTmp <= 2.0f * fLSqr * rkBox.GetHalfSideLengths().X) { fT = fTmp / fLSqr; fLSqr += kDir.X * kDir.X; fTmp = kPpE.X - fT; fDelta = kDir.Y * kPmE.Y + kDir.Z * kPpE.Z + kDir.X * fTmp; fParam = -fDelta / fLSqr; sqrDistance += kPmE.Y * kPmE.Y + kPpE.Z * kPpE.Z + fTmp * fTmp + fDelta * fParam; pfLParam = fParam; kPnt.Y = rkBox.GetHalfSideLengths().Y; kPnt.Z = -rkBox.GetHalfSideLengths().Z; kPnt.X = fT - rkBox.GetHalfSideLengths().X; } else { fLSqr += kDir.X * kDir.X; fDelta = kDir.Y * kPmE.Y + kDir.Z * kPpE.Z + kDir.X * kPmE.X; fParam = -fDelta / fLSqr; sqrDistance += kPmE.Y * kPmE.Y + kPpE.Z * kPpE.Z + kPmE.X * kPmE.X + fDelta * fParam; pfLParam = fParam; kPnt.Y = rkBox.GetHalfSideLengths().Y; kPnt.Z = -rkBox.GetHalfSideLengths().Z; kPnt.X = rkBox.GetHalfSideLengths().X; } } else { // v.Z < -e.Z, v.X < -e.X fLSqr = kDir.Y * kDir.Y + kDir.X * kDir.X; fTmp = fLSqr * kPpE.Z - kDir.Z * (kDir.Y * kPmE.Y + kDir.X * kPpE.X); if (fTmp >= 0.0f) { // v.Z-edge is closest if (fTmp <= 2.0f * fLSqr * rkBox.GetHalfSideLengths().Z) { fT = fTmp / fLSqr; fLSqr += kDir.Z * kDir.Z; fTmp = kPpE.Z - fT; fDelta = kDir.Y * kPmE.Y + kDir.Z * fTmp + kDir.X * kPpE.X; fParam = -fDelta / fLSqr; sqrDistance += kPmE.Y * kPmE.Y + fTmp * fTmp + kPpE.X * kPpE.X + fDelta * fParam; pfLParam = fParam; kPnt.Y = rkBox.GetHalfSideLengths().Y; kPnt.Z = fT - rkBox.GetHalfSideLengths().Z; kPnt.X = -rkBox.GetHalfSideLengths().X; } else { fLSqr += kDir.Z * kDir.Z; fDelta = kDir.Y * kPmE.Y + kDir.Z * kPmE.Z + kDir.X * kPpE.X; fParam = -fDelta / fLSqr; sqrDistance += kPmE.Y * kPmE.Y + kPmE.Z * kPmE.Z + kPpE.X * kPpE.X + fDelta * fParam; pfLParam = fParam; kPnt.Y = rkBox.GetHalfSideLengths().Y; kPnt.Z = rkBox.GetHalfSideLengths().Z; kPnt.X = -rkBox.GetHalfSideLengths().X; } return; } fLSqr = kDir.Y * kDir.Y + kDir.Z * kDir.Z; fTmp = fLSqr * kPpE.X - kDir.X * (kDir.Y * kPmE.Y + kDir.Z * kPpE.Z); if (fTmp >= 0.0f) { // v.X-edge is closest if (fTmp <= (2.0f * fLSqr * rkBox.GetHalfSideLengths().X)) { fT = fTmp / fLSqr; fLSqr += kDir.X * kDir.X; fTmp = kPpE.X - fT; fDelta = kDir.Y * kPmE.Y + kDir.Z * kPpE.Z + kDir.X * fTmp; fParam = -fDelta / fLSqr; sqrDistance += kPmE.Y * kPmE.Y + kPpE.Z * kPpE.Z + fTmp * fTmp + fDelta * fParam; pfLParam = fParam; kPnt.Y = rkBox.GetHalfSideLengths().Y; kPnt.Z = -rkBox.GetHalfSideLengths().Z; kPnt.X = fT - rkBox.GetHalfSideLengths().X; } else { fLSqr += kDir.X * kDir.X; fDelta = kDir.Y * kPmE.Y + kDir.Z * kPpE.Z + kDir.X * kPmE.X; fParam = -fDelta / fLSqr; sqrDistance += kPmE.Y * kPmE.Y + kPpE.Z * kPpE.Z + kPmE.X * kPmE.X + fDelta * fParam; pfLParam = fParam; kPnt.Y = rkBox.GetHalfSideLengths().Y; kPnt.Z = -rkBox.GetHalfSideLengths().Z; kPnt.X = rkBox.GetHalfSideLengths().X; } return; } // (v.Z,v.X)-corner is closest fLSqr += kDir.X * kDir.X; fDelta = kDir.Y * kPmE.Y + kDir.Z * kPpE.Z + kDir.X * kPpE.X; fParam = -fDelta / fLSqr; sqrDistance += kPmE.Y * kPmE.Y + kPpE.Z * kPpE.Z + kPpE.X * kPpE.X + fDelta * fParam; pfLParam = fParam; kPnt.Y = rkBox.GetHalfSideLengths().Y; kPnt.Z = -rkBox.GetHalfSideLengths().Z; kPnt.X = -rkBox.GetHalfSideLengths().X; } } }
/// <summary> /// SqrDistance /// </summary> /// <param name="line"></param> /// <param name="box"></param> /// <param name="pfLParam"></param> /// <param name="pfBParam0"></param> /// <param name="pfBParam1"></param> /// <param name="pfBParam2"></param> /// <returns>float</returns> public static float SqrDistance(Line line, Box box, out float pfLParam, out float pfBParam0, out float pfBParam1, out float pfBParam2) { // compute coordinates of line in box coordinate system Vector3 diff = line.Origin - box.GetCentre(); Vector3 pnt = new Vector3(Vector3.Dot(diff, box.Orientation.Right), Vector3.Dot(diff, box.Orientation.Up), Vector3.Dot(diff, box.Orientation.Backward)); Vector3 kDir = new Vector3(Vector3.Dot(line.Dir, box.Orientation.Right), Vector3.Dot(line.Dir, box.Orientation.Up), Vector3.Dot(line.Dir, box.Orientation.Backward)); // Apply reflections so that direction vector has nonnegative components. bool reflect0 = false; bool reflect1 = false; bool reflect2 = false; pfLParam = 0; if (kDir.X < 0.0f) { pnt.X = -pnt.X; kDir.X = -kDir.X; reflect0 = true; } if (kDir.Y < 0.0f) { pnt.Y = -pnt.Y; kDir.Y = -kDir.Y; reflect1 = true; } if (kDir.Z < 0.0f) { pnt.Z = -pnt.Z; kDir.Z = -kDir.Z; reflect2 = true; } float sqrDistance = 0.0f; if (kDir.X > 0.0f) { if (kDir.Y > 0.0f) { if (kDir.Z > 0.0f) { // (+,+,+) Vector3 kPmE = pnt - box.GetHalfSideLengths(); float prodDxPy = kDir.X * kPmE.Y; float prodDyPx = kDir.Y * kPmE.X; float prodDzPx, prodDxPz, prodDzPy, prodDyPz; if (prodDyPx >= prodDxPy) { prodDzPx = kDir.Z * kPmE.X; prodDxPz = kDir.X * kPmE.Z; if (prodDzPx >= prodDxPz) { //Face(0,1,2) FaceA(ref pnt, kDir, box, kPmE, out pfLParam, ref sqrDistance); } else { //Face(2,0,1) FaceB(ref pnt, kDir, box, kPmE, out pfLParam, ref sqrDistance); } } else { prodDzPy = kDir.Z * kPmE.Y; prodDyPz = kDir.Y * kPmE.Z; if (prodDzPy >= prodDyPz) { //Face(1,2,0) FaceC(ref pnt, kDir, box, kPmE, out pfLParam, ref sqrDistance); } else { //Face(2,0,1) FaceB(ref pnt, kDir, box, kPmE, out pfLParam, ref sqrDistance); } } } else { // (+,+,0) float pmE0 = pnt.X - box.GetHalfSideLengths().X; float pmE1 = pnt.Y - box.GetHalfSideLengths().Y; float prod0 = kDir.Y * pmE0; float prod1 = kDir.X * pmE1; float delta, invLSqur, inv; if (prod0 >= prod1) { // line intersects P[i0] = e[i0] pnt.X = box.GetHalfSideLengths().X; float ppE1 = pnt.Y + box.GetHalfSideLengths().Y; delta = prod0 - kDir.X * ppE1; if (delta >= 0.0f) { invLSqur = 1.0f / (kDir.X * kDir.X + kDir.Y * kDir.Y); sqrDistance += delta * delta * invLSqur; pnt.Y = -box.GetHalfSideLengths().Y; pfLParam = -(kDir.X * pmE0 + kDir.Y * ppE1) * invLSqur; } else { inv = 1.0f / kDir.X; pnt.Y -= prod0 * inv; pfLParam = -pmE0 * inv; } } else { // line intersects P[i1] = e[i1] pnt.Y = box.GetHalfSideLengths().Y; float ppE0 = pnt.X + box.GetHalfSideLengths().X; delta = prod1 - kDir.Y * ppE0; if (delta >= 0.0f) { invLSqur = 1.0f / (kDir.X * kDir.X + kDir.Y * kDir.Y); sqrDistance += delta * delta * invLSqur; pnt.X = -box.GetHalfSideLengths().X; pfLParam = -(kDir.X * ppE0 + kDir.Y * pmE1) * invLSqur; } else { inv = 1.0f / kDir.Y; pnt.X -= prod1 * inv; pfLParam = -pmE1 * inv; } } if (pnt.Z < -box.GetHalfSideLengths().Z) { delta = pnt.Z + box.GetHalfSideLengths().Z; sqrDistance += delta * delta; pnt.Z = -box.GetHalfSideLengths().Z; } else if (pnt.Z > box.GetHalfSideLengths().Z) { delta = pnt.Z - box.GetHalfSideLengths().Z; sqrDistance += delta * delta; pnt.Z = box.GetHalfSideLengths().Z; } } } else { if (kDir.Z > 0.0f) { // (+,0,+) float pmE0 = pnt.X - box.GetHalfSideLengths().X; float pmE1 = pnt.Z - box.GetHalfSideLengths().Z; float prod0 = kDir.Z * pmE0; float prod1 = kDir.X * pmE1; float delta, invLSqur, inv; if (prod0 >= prod1) { // line intersects P[i0] = e[i0] pnt.X = box.GetHalfSideLengths().X; float ppE1 = pnt.Z + box.GetHalfSideLengths().Z; delta = prod0 - kDir.X * ppE1; if (delta >= 0.0f) { invLSqur = 1.0f / (kDir.X * kDir.X + kDir.Z * kDir.Z); sqrDistance += delta * delta * invLSqur; pnt.Z = -box.GetHalfSideLengths().Z; pfLParam = -(kDir.X * pmE0 + kDir.Z * ppE1) * invLSqur; } else { inv = 1.0f / kDir.X; pnt.Z -= prod0 * inv; pfLParam = -pmE0 * inv; } } else { // line intersects P[i1] = e[i1] pnt.Z = box.GetHalfSideLengths().Z; float ppE0 = pnt.X + box.GetHalfSideLengths().X; delta = prod1 - kDir.Z * ppE0; if (delta >= 0.0f) { invLSqur = 1.0f / (kDir.X * kDir.X + kDir.Z * kDir.Z); sqrDistance += delta * delta * invLSqur; pnt.X = -box.GetHalfSideLengths().X; pfLParam = -(kDir.X * ppE0 + kDir.Z * pmE1) * invLSqur; } else { inv = 1.0f / kDir.Z; pnt.X -= prod1 * inv; pfLParam = -pmE1 * inv; } } if (pnt.Y < -box.GetHalfSideLengths().Y) { delta = pnt.Y + box.GetHalfSideLengths().Y; sqrDistance += delta * delta; pnt.Y = -box.GetHalfSideLengths().Y; } else if (pnt.Y > box.GetHalfSideLengths().Y) { delta = pnt.Y - box.GetHalfSideLengths().Y; sqrDistance += delta * delta; pnt.Y = box.GetHalfSideLengths().Y; } } else { // (+,0,0) float pmE0 = pnt.X - box.GetHalfSideLengths().X; float pmE1 = pnt.Y - box.GetHalfSideLengths().Y; float prod0 = kDir.Y * pmE0; float prod1 = kDir.X * pmE1; float delta, invLSqur, inv; if (prod0 >= prod1) { // line intersects P[i0] = e[i0] pnt.X = box.GetHalfSideLengths().X; float ppE1 = pnt.Y + box.GetHalfSideLengths().Y; delta = prod0 - kDir.X * ppE1; if (delta >= 0.0f) { invLSqur = 1.0f / (kDir.X * kDir.X + kDir.Y * kDir.Y); sqrDistance += delta * delta * invLSqur; pnt.Y = -box.GetHalfSideLengths().Y; pfLParam = -(kDir.X * pmE0 + kDir.Y * ppE1) * invLSqur; } else { inv = 1.0f / kDir.X; pnt.Y -= prod0 * inv; pfLParam = -pmE0 * inv; } } else { // line intersects P[i1] = e[i1] pnt.Y = box.GetHalfSideLengths().Y; float ppE0 = pnt.X + box.GetHalfSideLengths().X; delta = prod1 - kDir.Y * ppE0; if (delta >= 0.0f) { invLSqur = 1.0f / (kDir.X * kDir.X + kDir.Y * kDir.Y); sqrDistance += delta * delta * invLSqur; pnt.X = -box.GetHalfSideLengths().X; pfLParam = -(kDir.X * ppE0 + kDir.Y * pmE1) * invLSqur; } else { inv = 1.0f / kDir.Y; pnt.X -= prod1 * inv; pfLParam = -pmE1 * inv; } } if (pnt.Z < -box.GetHalfSideLengths().Z) { delta = pnt.Z + box.GetHalfSideLengths().Z; sqrDistance += delta * delta; pnt.Z = -box.GetHalfSideLengths().Z; } else if (pnt.Z > box.GetHalfSideLengths().Z) { delta = pnt.Z - box.GetHalfSideLengths().Z; sqrDistance += delta * delta; pnt.Z = box.GetHalfSideLengths().Z; } } } } else { if (kDir.Y > 0.0f) { if (kDir.Z > 0.0f) { float pmE0 = pnt.Y - box.GetHalfSideLengths().Y; float pmE1 = pnt.Z - box.GetHalfSideLengths().Z; float prod0 = kDir.Z * pmE0; float prod1 = kDir.Y * pmE1; float delta, invLSqur, inv; if (prod0 >= prod1) { // line intersects P[i0] = e[i0] pnt.Y = box.GetHalfSideLengths().Y; float ppE1 = pnt.Z + box.GetHalfSideLengths().Z; delta = prod0 - kDir.Y * ppE1; if (delta >= 0.0f) { invLSqur = 1.0f / (kDir.Y * kDir.Y + kDir.Z * kDir.Z); sqrDistance += delta * delta * invLSqur; pnt.Z = -box.GetHalfSideLengths().Z; pfLParam = -(kDir.Y * pmE0 + kDir.Z * ppE1) * invLSqur; } else { inv = 1.0f / kDir.Y; pnt.Z -= prod0 * inv; pfLParam = -pmE0 * inv; } } else { // line intersects P[i1] = e[i1] pnt.Z = box.GetHalfSideLengths().Z; float ppE0 = pnt.Y + box.GetHalfSideLengths().Y; delta = prod1 - kDir.Z * ppE0; if (delta >= 0.0f) { invLSqur = 1.0f / (kDir.Y * kDir.Y + kDir.Z * kDir.Z); sqrDistance += delta * delta * invLSqur; pnt.Y = -box.GetHalfSideLengths().Y; pfLParam = -(kDir.Y * ppE0 + kDir.Z * pmE1) * invLSqur; } else { inv = 1.0f / kDir.Z; pnt.Y -= prod1 * inv; pfLParam = -pmE1 * inv; } } if (pnt.X < -box.GetHalfSideLengths().X) { delta = pnt.X + box.GetHalfSideLengths().X; sqrDistance += delta * delta; pnt.X = -box.GetHalfSideLengths().X; } else if (pnt.X > box.GetHalfSideLengths().X) { delta = pnt.X - box.GetHalfSideLengths().X; sqrDistance += delta * delta; pnt.X = box.GetHalfSideLengths().X; } } else { // (0,+,0) float delta; pfLParam = (box.GetHalfSideLengths().Y - pnt.Y) / kDir.Y; pnt.Y = box.GetHalfSideLengths().Y; if (pnt.X < -box.GetHalfSideLengths().X) { delta = pnt.X + box.GetHalfSideLengths().X; sqrDistance += delta * delta; pnt.X = -box.GetHalfSideLengths().X; } else if (pnt.X > box.GetHalfSideLengths().X) { delta = pnt.X - box.GetHalfSideLengths().X; sqrDistance += delta * delta; pnt.X = box.GetHalfSideLengths().X; } if (pnt.Z < -box.GetHalfSideLengths().Z) { delta = pnt.Z + box.GetHalfSideLengths().Z; sqrDistance += delta * delta; pnt.Z = -box.GetHalfSideLengths().Z; } else if (pnt.Z > box.GetHalfSideLengths().Z) { delta = pnt.Z - box.GetHalfSideLengths().Z; sqrDistance += delta * delta; pnt.Z = box.GetHalfSideLengths().Z; } } } else { if (kDir.Z > 0.0f) { float delta; pfLParam = (box.GetHalfSideLengths().Z - pnt.Z) / kDir.Z; pnt.Z = box.GetHalfSideLengths().Z; if (pnt.X < -box.GetHalfSideLengths().X) { delta = pnt.X + box.GetHalfSideLengths().X; sqrDistance += delta * delta; pnt.X = -box.GetHalfSideLengths().X; } else if (pnt.X > box.GetHalfSideLengths().X) { delta = pnt.X - box.GetHalfSideLengths().X; sqrDistance += delta * delta; pnt.X = box.GetHalfSideLengths().X; } if (pnt.Y < -box.GetHalfSideLengths().Y) { delta = pnt.Y + box.GetHalfSideLengths().Y; sqrDistance += delta * delta; pnt.Y = -box.GetHalfSideLengths().Y; } else if (pnt.Y > box.GetHalfSideLengths().Y) { delta = pnt.Y - box.GetHalfSideLengths().Y; sqrDistance += delta * delta; pnt.Y = box.GetHalfSideLengths().Y; } } else { // (0,0,0) float delta; if (pnt.X < -box.GetHalfSideLengths().X) { delta = pnt.X + box.GetHalfSideLengths().X; sqrDistance += delta * delta; pnt.X = -box.GetHalfSideLengths().X; } else if (pnt.X > box.GetHalfSideLengths().X) { delta = pnt.X - box.GetHalfSideLengths().X; sqrDistance += delta * delta; pnt.X = box.GetHalfSideLengths().X; } if (pnt.Y < -box.GetHalfSideLengths().Y) { delta = pnt.Y + box.GetHalfSideLengths().Y; sqrDistance += delta * delta; pnt.Y = -box.GetHalfSideLengths().Y; } else if (pnt.Y > box.GetHalfSideLengths().Y) { delta = pnt.Y - box.GetHalfSideLengths().Y; sqrDistance += delta * delta; pnt.Y = box.GetHalfSideLengths().Y; } if (pnt.Z < -box.GetHalfSideLengths().Z) { delta = pnt.Z + box.GetHalfSideLengths().Z; sqrDistance += delta * delta; pnt.Z = -box.GetHalfSideLengths().Z; } else if (pnt.Z > box.GetHalfSideLengths().Z) { delta = pnt.Z - box.GetHalfSideLengths().Z; sqrDistance += delta * delta; pnt.Z = box.GetHalfSideLengths().Z; } } } } // undo reflections if (reflect0) pnt.X = -pnt.X; if (reflect1) pnt.Y = -pnt.Y; if (reflect2) pnt.Z = -pnt.Z; pfBParam0 = pnt.X; pfBParam1 = pnt.Y; pfBParam2 = pnt.Z; return MathHelper.Max(sqrDistance, 0.0f); }
/// <summary> /// SqrDistance /// </summary> /// <param name="point"></param> /// <param name="box"></param> /// <param name="pfBParam0"></param> /// <param name="pfBParam1"></param> /// <param name="pfBParam2"></param> /// <returns>float</returns> public static float SqrDistance(Vector3 point, Box box, out float pfBParam0, out float pfBParam1, out float pfBParam2) { // compute coordinates of point in box coordinate system Vector3 kDiff = point - box.GetCentre(); Vector3 kClosest = new Vector3(Vector3.Dot(kDiff, box.Orientation.Right), Vector3.Dot(kDiff, box.Orientation.Up), Vector3.Dot(kDiff, box.Orientation.Backward)); // project test point onto box float fSqrDistance = 0.0f; float fDelta; if (kClosest.X < -box.GetHalfSideLengths().X) { fDelta = kClosest.X + box.GetHalfSideLengths().X; fSqrDistance += fDelta * fDelta; kClosest.X = -box.GetHalfSideLengths().X; } else if (kClosest.X > box.GetHalfSideLengths().X) { fDelta = kClosest.X - box.GetHalfSideLengths().X; fSqrDistance += fDelta * fDelta; kClosest.X = box.GetHalfSideLengths().X; } if (kClosest.Y < -box.GetHalfSideLengths().Y) { fDelta = kClosest.Y + box.GetHalfSideLengths().Y; fSqrDistance += fDelta * fDelta; kClosest.Y = -box.GetHalfSideLengths().Y; } else if (kClosest.Y > box.GetHalfSideLengths().Y) { fDelta = kClosest.Y - box.GetHalfSideLengths().Y; fSqrDistance += fDelta * fDelta; kClosest.Y = box.GetHalfSideLengths().Y; } if (kClosest.Z < -box.GetHalfSideLengths().Z) { fDelta = kClosest.Z + box.GetHalfSideLengths().Z; fSqrDistance += fDelta * fDelta; kClosest.Z = -box.GetHalfSideLengths().Z; } else if (kClosest.Z > box.GetHalfSideLengths().Z) { fDelta = kClosest.Z - box.GetHalfSideLengths().Z; fSqrDistance += fDelta * fDelta; kClosest.Z = box.GetHalfSideLengths().Z; } pfBParam0 = kClosest.X; pfBParam1 = kClosest.Y; pfBParam2 = kClosest.Z; return MathHelper.Max(fSqrDistance, 0.0f); }
public override void Initialize() { Body = new Body(); Skin = new CollisionSkin(Body); Body.CollisionSkin = Skin; radius = 12; float length = 3; //Capsule middle = new Capsule(Vector3.Zero, Matrix.Identity, radius, length - 2.0f * radius); float sideLength = 2.0f * radius / (float)Math.Sqrt(2.0d); Vector3 sides = new Vector3(-0.5f * sideLength, -0.5f * sideLength, -radius); Box supply0 = new Box(sides, Matrix.Identity, new Vector3(sideLength, sideLength, length)); Box supply1 = new Box(Vector3.Transform(sides, Matrix.CreateRotationZ(MathHelper.PiOver4)), Matrix.CreateRotationZ(MathHelper.PiOver4), new Vector3(sideLength, sideLength, length)); Box supply2 = new Box(Vector3.Transform(sides, Matrix.CreateRotationZ( (MathHelper.PiOver4 * 0.5f) )), Matrix.CreateRotationZ( (MathHelper.PiOver4 * 0.5f) ), new Vector3(sideLength, sideLength, length)); Box supply3 = new Box(Vector3.Transform(sides, Matrix.CreateRotationZ((MathHelper.PiOver4 * 1.5f))), Matrix.CreateRotationZ((MathHelper.PiOver4 * 1.5f)), new Vector3(sideLength, sideLength, length)); //Skin.AddPrimitive(middle, new MaterialProperties(0.8f, 0.8f, 0.7f)); Skin.AddPrimitive(supply0, new MaterialProperties(0.8f, 0.8f, 0.7f)); Skin.AddPrimitive(supply1, new MaterialProperties(0.8f, 0.8f, 0.7f)); Skin.AddPrimitive(supply2, new MaterialProperties(0.8f, 0.8f, 0.7f)); Skin.AddPrimitive(supply3, new MaterialProperties(0.8f, 0.8f, 0.7f)); Vector3 com = SetMass(1.0f); Body.MoveTo(position, Matrix.Identity); Skin.ApplyLocalTransform(new Transform(-com, Matrix.Identity)); #region Manually set body inertia float cylinderMass = Body.Mass; float comOffs = (length - 2.0f * radius) * 0.5f; ; float Ixx = 0.5f * cylinderMass * radius * radius + cylinderMass * comOffs * comOffs; float Iyy = 0.25f * cylinderMass * radius * radius + (1.0f / 12.0f) * cylinderMass * length * length + cylinderMass * comOffs * comOffs; float Izz = Iyy; Body.SetBodyInertia(Ixx, Iyy, Izz); #endregion Body.EnableBody(); Body.ExternalData = this; SetBody(rotation); }
private Gobject CreateHighFrictionCube() { Vector3 size = new Vector3(1, 1, 1); // position of box was upper leftmost corner // body has world position // skin is relative to the body Box boxPrimitive = new Box(-.5f * size, Matrix.Identity, size); // relative to the body, the position is the top left-ish corner instead of the center, so subtract from the center, half of all sides to get that point. Gobject box = new Gobject( Vector3.Zero, // position can be setup just following call to assetManager.GetNewInstance size / 2, boxPrimitive, MaterialTable.MaterialID.NotBouncyRough, cubeModel, 0 // asset name is set automatically by asset manager when requested ); return box; }
protected override void LoadSpecific() { base.LoadSpecific(); if (m_Body != null) { // Set skin to the body m_Body.CollisionSkin = m_Skin; // Check the skin was successfully created and add this // custom dice as a primitive to the collision skin if (m_Skin != null) { Vector3 sideLengths = (m_BoundingBox.Max - m_BoundingBox.Min); if (sideLengths.Y <= 0) sideLengths.Y = 0.1f; Box box = new Box(Vector3.Zero, Matrix.Identity, sideLengths); m_Skin.AddPrimitive(box, (int)MaterialTable.MaterialID.BouncyRough); // Set mass m_Mass = SetMass(7.0f); // Move the body to correct position initially m_Body.MoveTo(transform.Position, Matrix.Identity); // Apply transform to skin m_Skin.ApplyLocalTransform(new JigLibX.Math.Transform(-m_Mass, Matrix.Identity)); // make sure it isn't in the scene and is disabled Disable(); } } }