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();
                }
            }
        }
Exemple #3
0
        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();
        }
Exemple #5
0
        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);
        }
Exemple #6
0
        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);
        }
Exemple #8
0
      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);
        }
Exemple #10
0
        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);
        }
Exemple #11
0
        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;
                }
            }
        }
Exemple #13
0
        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);
        }
Exemple #14
0
        // 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);
        }
Exemple #16
0
        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();
        }
Exemple #17
0
        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;
        }
Exemple #25
0
        /// <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);
            }
        }
Exemple #26
0
        /// <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;
                }
            }
        }
Exemple #27
0
        /// <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);
        }
Exemple #28
0
        /// <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);
        }
Exemple #29
0
        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);
        }
Exemple #30
0
        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();
                }
            }
        }