Example #1
0
        public override CollisionShape Clone()
        {
            CollisionCapsule rv = new CollisionCapsule(bottomcenter, topcenter, capRadius);

            rv.handle    = this.handle;
            rv.timeStamp = this.timeStamp;
            return(rv);
        }
        private void FourCollisionsButton_Click(object sender, EventArgs e)
        {
            CollisionAPI API = new CollisionAPI();
            // Create some obstacles, at 4 corners of a square
            List<CollisionShape> shapes = new List<CollisionShape>();

            CollisionSphere sphere = new CollisionSphere(new Vector3(0f, 0f, 2f), 1f);
            shapes.Add(sphere);
            API.AddCollisionShape(sphere, 1);

            CollisionCapsule capsule = new CollisionCapsule(new Vector3(10f,0f,0f),
                                                            new Vector3(10f,0f,4f),
                                                            1f);
            shapes.Add(capsule);
            API.AddCollisionShape(capsule, 2);

            // Now, an AABB
            CollisionAABB aabb = new CollisionAABB(new Vector3(9.5f,9.5f,0f),
                                                   new Vector3(10.5f,10.5f,4f));
            shapes.Add(aabb);
            API.AddCollisionShape(aabb, 3);

            CollisionOBB obb = new CollisionOBB(new Vector3(0f,10f,2),
                                                   new Vector3[3] {
                                                       new Vector3(1f,0f,0f),
                                                       new Vector3(0f,1f,0f),
                                                       new Vector3(0f,0f,1f)},
                                                new Vector3(1f, 1f, 1f));
            shapes.Add(obb);
            API.AddCollisionShape(obb, 4);

            FileStream f = new FileStream("C:\\Junk\\DumpSphereTree.txt", FileMode.Create, FileAccess.Write);
            StreamWriter writer = new StreamWriter(f);

            API.DumpSphereTree(writer);
            API.SphereTreeRoot.VerifySphereTree();

            // Now a moving object capsule in the center of the square
            CollisionCapsule moCap = new CollisionCapsule(new Vector3(5f,5f,0f),
                                                          new Vector3(5f,5f,4f),
                                                          1f);

            // Remember where the moving object started
            Vector3 start = moCap.center;

            // Move the moving object toward each of the obstacles
            foreach (CollisionShape s in shapes) {
                moCap.AddDisplacement(start - moCap.center);
                MoveToObject(writer, API, s, moCap);
            }

            writer.Close();
        }
Example #3
0
        public static void CreateRenderedNodes(CollisionShape shape, int id, ref List <RenderedNode> renderedNodes)
        {
            // To keep all the rendering stuff internal to this file, we
            // reach inside of collision objects to create the rendered
            // shapes
            if (renderedNodes == null)
            {
                renderedNodes = new List <RenderedNode>();
            }
            switch (shape.ShapeType())
            {
            case ShapeEnum.ShapeSphere:
                renderedNodes.Add(NewRenderedSphere(id, 0, shape.center, shape.radius * MO.DivMeter));
                break;

            case ShapeEnum.ShapeCapsule:
                CollisionCapsule c = (CollisionCapsule)shape;
                float            r = c.capRadius * MO.DivMeter;
                renderedNodes.Add(NewRenderedSphere(id, 0, c.bottomcenter, r));
                renderedNodes.Add(NewRenderedSphere(id, 1, c.topcenter, r));
                Vector3 seg = (c.topcenter - c.bottomcenter);
                renderedNodes.Add(NewRenderedObject("unit_cylinder.mesh",
                                                    id, 2, c.center,
                                                    new Vector3(r, seg.Length * MO.DivMeter, r),
                                                    new Vector3(0f, 1f, 0f).GetRotationTo(seg)));
                break;

            case ShapeEnum.ShapeAABB:
                renderedNodes.Add(NewRenderedBox(id, 0, ((CollisionAABB)shape).OBB()));
                break;

            case ShapeEnum.ShapeOBB:
                renderedNodes.Add(NewRenderedBox(id, 0, (CollisionOBB)shape));
                break;
            }
        }
        // This method is the callback by which the forests controlled
        // by the scene manager tell us about SpeedTrees.
        private void AddTreeObstacles(SpeedTreeWrapper tree)
        {
            // If this tree didn't use to be in range but now is
            V3 vp = tree.TreePosition;
            Vector3 p = new Vector3(vp.x, vp.y, vp.z);
            // Find the tile in question
            int tileX, tileZ;
            WorldToTileCoords(p, out tileX, out tileZ);
            bool oir = InRange(tileXCenter, tileZCenter, tileX, tileZ);
            bool nir = InRange(newTileXCenter, newTileZCenter, tileX, tileZ);
            //             if (MO.DoLog)
            //                 MO.Log(String.Format("For tree at {0}, testing !InRange({1},{2},{3},{4}) = {5} && InRange({6},{7},{8},{9}) = {10}",
            //                                      MO.MeterString(p),tileXCenter, tileZCenter, tileX, tileZ, MO.Bool(!oir),
            //                                      newTileXCenter, newTileZCenter, tileX, tileZ, MO.Bool(nir)));
            if (!oir && nir) {
                int tX = TileToArrayIndex(tileX, newTileXCenter);
                int tZ = TileToArrayIndex(tileZ, newTileZCenter);
                uint count = tree.CollisionObjectCount;
                long handle = ComposeHandle(tileX, tileZ);
                CollisionShape shape = null;
                if (MO.DoLog) {
                    MO.Log(string.Format("Adding tree at {0}, tiles[{1},{2}] = {3}, tile coords[{4},{5}], obj. new count {6}",
                                      MO.MeterString(p), tX, tZ, tiles[tX,tZ], tileX, tileZ, count));
                    MO.Log(string.Format("Handle {0}, oldcenter {1}, newcenter {2}",
                                         MO.HandleString(handle), MO.MeterString(tileWorldCenter), MO.MeterString(newTileWorldCenter)));
                }
                float size = 0f;
                float variance = 0f;
                tree.GetTreeSize(ref size, ref variance);
                float scaleFactor = size / tree.OriginalSize;
                for (uint i=0; i<count; i++) {
                    TreeCollisionObject tco = tree.CollisionObject(i);
                    Vector3 cp = new Vector3(tco.position.x, tco.position.y, tco.position.z) * scaleFactor + p;
                    Vector3 cd = new Vector3(tco.dimensions.x, tco.dimensions.y, tco.dimensions.z) * scaleFactor;
                    switch ((CollisionObjectType)tco.type) {
                    case CollisionObjectType.ColSphere:
                        shape = new CollisionSphere(cp, cd.x);
                        break;
                    case CollisionObjectType.ColCylinder:
                        // We treat it as a capsule, but we raise the
                        // capsule up by the capRadius, and shorten
                        // the segment by the double the capRadius
                        Vector3 top = cp;
                        top.y += cd.y - cd.x * 2f;
                        cp.y += cd.x;
                        shape = new CollisionCapsule(cp, top, cd.x);
                        break;
                    case CollisionObjectType.ColBox:
                        Vector3 tp = cp;
                        tp.x -= cd.x * .5f;
                        tp.y -= cd.y * .5f;
                        shape = new CollisionAABB(tp, tp + cd);
                        break;
                    }
                    collisionAPI.AddCollisionShape(shape, handle);
                    tiles[tX, tZ]++;
                    objectsAdded++;

                    if (MO.DoLog) {
                        MO.Log(string.Format(" tiles[{0},{1}] = {2}, tile at [{3},{4}] after adding shape {5}",
                                          tX, tZ, tiles[tX, tZ], tileX, tileZ, shape.ToString()));
                    }
                }
            }
        }
        public static bool TestCapsuleOBB(CollisionCapsule a, CollisionOBB b, CollisionParms parms)
        {
            SegOBBParams obbParms = new SegOBBParams(true);
            Segment s = Segment.SegmentFromStartAndEnd(a.bottomcenter, a.topcenter);
            if (SqrDistSegOBB(s, b, obbParms) < a.capRadius * a.capRadius) {
            // If parms.pfLParam == 0, closest is bottomcenter; if == 1,
            // closest is topcenter.

            Vector3 d = a.bottomcenter + obbParms.pfLParam * s.direction;
            // pfBVec is relative to the center of the box, but in box
            // coords.
            Vector3 f = b.center;
            for (int i=0; i<3; i++)
            f += obbParms.pfBVec[i] * b.axes[i];
            Vector3 n = f - d;
            parms.SetNormPart(n);
            parms.SetNormObstacle(-n);
            if (MO.DoLog) {
            MO.Log(" TestCapsuleOBB: pfLParam {0}, pfBVec {1}", obbParms.pfLParam, obbParms.pfBVec);
            MO.Log(" TestCapsuleOBB: d {0}, f {1}", f, d);
            MO.Log(" -n {0}", -n);
            }
            return true;
            }
            else
            return false;
        }
 public static bool TestCapsuleCapsule(CollisionCapsule c1, CollisionCapsule c2,
                               CollisionParms parms)
 {
     // Compute (squared) distance between the inner structures of the capsules
     float s, t;
     Vector3 p1, p2;
     float d = ClosestPtSegmentSegment(c1.bottomcenter, c1.topcenter,
                               c2.bottomcenter, c2.topcenter,
                               out s, out t, out p1, out p2);
     float r = c1.capRadius + c2.capRadius;
     Vector3 n = p2 - p1;
     parms.SetNormPart(n);
     parms.SetNormObstacle(-n);
     return d < r * r;
 }
 public static bool TestCapsuleAABB(CollisionCapsule a, CollisionAABB b, CollisionParms parms)
 {
     // Convert the AABB into an OBB, then run the OBBOBB test.
     // Not the most efficient algorithm but it gets the job
     // done.
     CollisionOBB newB = new CollisionOBB(b.center,
                                  UnitBasisVectors,
                                  (b.max - b.min) * .5f);
     return TestCapsuleOBB(a, newB, parms);
 }
Example #8
0
        private static void TestPhysics( string srcDir, string dstDir, string name )
        {
            float OneMeter = 1000;
            PhysicsData pd = new PhysicsData();
            Vector3 center = new Vector3( 10 * OneMeter, 1 * OneMeter, 1 * OneMeter );
            Vector3[] obbAxes = new Vector3[ 3 ];
            obbAxes[ 0 ] = new Vector3( 1, 0, -1 );
            obbAxes[ 0 ].Normalize();
            obbAxes[ 1 ] = Vector3.UnitY;
            obbAxes[ 2 ] = new Vector3( 1, 0, 1 );
            obbAxes[ 2 ].Normalize();
            Vector3 obbExtents = new Vector3( 2.5f * OneMeter, 1 * OneMeter, 1 * OneMeter );
            CollisionOBB obb = new CollisionOBB( center, obbAxes, obbExtents );
            pd.AddCollisionShape( "submesh01", obb );
            CollisionAABB aabb = new CollisionAABB( center - obbExtents, center + obbExtents );
            pd.AddCollisionShape( "submesh01", aabb );
            CollisionSphere sphere = new CollisionSphere( center, 2 * OneMeter );
            pd.AddCollisionShape( "submesh01", sphere );
            Vector3 capExtents = new Vector3( -1 * OneMeter, 0, 0 );
            CollisionCapsule capsule = new CollisionCapsule( center + capExtents, center - capExtents, .5f * OneMeter );
            pd.AddCollisionShape( "submesh01", capsule );
            PhysicsSerializer ps = new PhysicsSerializer();
            ps.ExportPhysics( pd, name );

            pd = new PhysicsData();
            ps.ImportPhysics( pd, name );
            foreach( string objectId in pd.GetCollisionObjects() )
            {
                log.InfoFormat( "Collision shapes for: {0}", objectId );
                List<CollisionShape> collisionShapes = pd.GetCollisionShapes( objectId );
                foreach( CollisionShape shape in collisionShapes )
                    log.InfoFormat( "Shape: {0}", shape );
            }
        }
        // Keep the code below, commented out, because it is useful
        // for debugging near plane issues
        // 		   private static int nearPlaneCollisionCount = 0;
        //         private static int nearPlaneNodeId = 99999;
        //         private static List<RenderedNode>[] nearPlaneRenderedNodes = new List<RenderedNode>[4] {
        //             new List<RenderedNode>(), new List<RenderedNode>(), new List<RenderedNode>(), new List<RenderedNode>() };
        //         private static CollisionCapsule[] nearPlaneCapsules = new CollisionCapsule[4];
        //        
        //         protected void CreateNearPlaneCapsules(Camera camera,
        //                                                Vector3 cameraPosition,
        //                                                Vector3 playerHeadPosition)
        //         {
        //             // Frame the clip plane with 4 narrow capsules
        //             // Start by finding the center of the near plane
        //             Vector3 toPlayer = (playerHeadPosition - cameraPosition).ToNormalized();
        //             Vector3 center = cameraPosition + (1.02f * camera.Near) * toPlayer;
        //             float thetaY = MathUtil.DegreesToRadians(camera.FOVy * 0.5f);
        //             float tanThetaY = MathUtil.Tan(thetaY);
        //             float tanThetaX = tanThetaY * camera.AspectRatio;
        //             Vector3 right = tanThetaX * camera.Near * (camera.Right.ToNormalized());
        //             Vector3 up = tanThetaY * camera.Near * (camera.Up.ToNormalized());
        //             Vector3 corner1 = center + right - up;
        //             Vector3 corner2 = center + right + up;
        //             Vector3 corner3 = center - right + up;
        //             Vector3 corner4 = center - right - up;
        //             nearPlaneCapsules[0] = new CollisionCapsule(corner1, corner2, Client.OneMeter * .001f);
        //             nearPlaneCapsules[1] = new CollisionCapsule(corner2, corner3, Client.OneMeter * .001f);
        //             nearPlaneCapsules[2] = new CollisionCapsule(corner3, corner4, Client.OneMeter * .001f);
        //             nearPlaneCapsules[3] = new CollisionCapsule(corner4, corner1, Client.OneMeter * .001f);
        //            
        //             RenderedNode.Scene = sceneManager;
        //             for (int i=0; i<4; i++) {
        //                 RenderedNode.RemoveNodeRendering(nearPlaneNodeId + i, ref nearPlaneRenderedNodes[i]);
        //                 RenderedNode.CreateRenderedNodes(nearPlaneCapsules[i], nearPlaneNodeId + i, ref nearPlaneRenderedNodes[i]);
        //             }
        //         }
        protected float FindAcceptableCameraPosition(Camera camera, Vector3 cameraPos, Vector3 cameraTarget)
        {
            //Logger.Log(0, "FindAcceptableCameraPosition cameraPos {0}, cameraTarget {1}", cameraPos, cameraTarget);

            // If there is no CollisionAPI object, punt
            CollisionAPI api = client.WorldManager.CollisionHelper;
            if (api == null)
                return (cameraPos - cameraTarget).Length;

            // Start by finding the point at which a narrow capsule
            // from the camera to the player intersects.  If it
            // doesn't, then set the point to the cameraPos.

            // Make a very narrow capsule between the camera and the player's head
            CollisionCapsule cap = new CollisionCapsule(cameraPos,
                                                        cameraTarget,
                                                        Client.OneMeter * .001f);  // 1 millimeter
            Vector3 newCameraPos = cameraPos;
            Vector3 unitTowardCamera = (newCameraPos - cameraTarget).ToNormalized();

            // Test for a collision, setting intersection if there is one.
            Vector3 intersection = Vector3.Zero;
            if (api.FindClosestCollision(cap, cameraTarget, cameraPos, ref intersection) != null) {
                // There is A collision - - set the new camera pos to
                // be the point of intersection
                newCameraPos = intersection - unitTowardCamera * camera.Near;
                //Logger.Log(0, "FindAcceptableCameraPosition: Thin cap collides at {0}", newCameraPos);
            }

            // Move a near-plane OBB forward from the point of
            // intersection until we find a place where the near plane
            // doesn't intersect any collision volumes

            Vector3 center = newCameraPos - camera.Near * unitTowardCamera;
            float thetaY = MathUtil.DegreesToRadians(camera.FOVy * 0.5f);
            float tanThetaY = MathUtil.Tan(thetaY);
            float tanThetaX = tanThetaY * camera.AspectRatio;

            // Compute the OBB axes and extents
            Vector3[] axes = new Vector3[3];
            Vector3 extents = Vector3.Zero;
            // The axis perpendicular to the near plane
            float obbDepth = 100f;  // 100 mm thick
            axes[0] = -unitTowardCamera;
            axes[1] = -axes[0].Cross(Vector3.UnitY).ToNormalized();
            axes[2] = -axes[1].Cross(axes[0]).ToNormalized();
            extents[0] = obbDepth;
            extents[1] = camera.Near * tanThetaX;
            extents[2] = camera.Near * tanThetaY;
            float len = (newCameraPos - cameraTarget).Length;
            float startingLen = len;
            CollisionOBB obb = new CollisionOBB(center, axes, extents);
            CollisionParms parms = new CollisionParms();
            while (len >= minThirdPersonDistance) {
                obb.center = cameraTarget + unitTowardCamera * len;
                bool collides = api.ShapeCollides(obb, parms);
                //Logger.Log(0, "FindAcceptableCameraPosition len {0}, obb center {1}, collides {2}", len, obb.center, collides);
                if (!collides)
                    break;
                //client.Write(string.Format("OBB collides; len {0}", len));
                len -= obbDepth;
            }
            // Len is less than the camera min distance, so just
            // return it
            //Logger.Log(0, "FindAcceptableCameraPosition: starting len {0} final len {1}", startingLen, len);
            return len;
        }
        // This method is the callback by which the forests controlled
        // by the scene manager tell us about SpeedTrees.
        private void AddTreeObstacles(SpeedTreeWrapper tree)
        {
            // If this tree didn't use to be in range but now is
            V3      vp = tree.TreePosition;
            Vector3 p  = new Vector3(vp.x, vp.y, vp.z);
            // Find the tile in question
            int tileX, tileZ;

            WorldToTileCoords(p, out tileX, out tileZ);
            bool oir = InRange(tileXCenter, tileZCenter, tileX, tileZ);
            bool nir = InRange(newTileXCenter, newTileZCenter, tileX, tileZ);

//             if (MO.DoLog)
//                 MO.Log(String.Format("For tree at {0}, testing !InRange({1},{2},{3},{4}) = {5} && InRange({6},{7},{8},{9}) = {10}",
//                                      MO.MeterString(p),tileXCenter, tileZCenter, tileX, tileZ, MO.Bool(!oir),
//                                      newTileXCenter, newTileZCenter, tileX, tileZ, MO.Bool(nir)));
            if (!oir && nir)
            {
                int            tX     = TileToArrayIndex(tileX, newTileXCenter);
                int            tZ     = TileToArrayIndex(tileZ, newTileZCenter);
                uint           count  = tree.CollisionObjectCount;
                long           handle = ComposeHandle(tileX, tileZ);
                CollisionShape shape  = null;
                if (MO.DoLog)
                {
                    MO.Log(string.Format("Adding tree at {0}, tiles[{1},{2}] = {3}, tile coords[{4},{5}], obj. new count {6}",
                                         MO.MeterString(p), tX, tZ, tiles[tX, tZ], tileX, tileZ, count));
                    MO.Log(string.Format("Handle {0}, oldcenter {1}, newcenter {2}",
                                         MO.HandleString(handle), MO.MeterString(tileWorldCenter), MO.MeterString(newTileWorldCenter)));
                }
                float size     = 0f;
                float variance = 0f;
                tree.GetTreeSize(ref size, ref variance);
                float scaleFactor = size / tree.OriginalSize;
                for (uint i = 0; i < count; i++)
                {
                    TreeCollisionObject tco = tree.CollisionObject(i);
                    Vector3             cp  = new Vector3(tco.position.x, tco.position.y, tco.position.z) * scaleFactor + p;
                    Vector3             cd  = new Vector3(tco.dimensions.x, tco.dimensions.y, tco.dimensions.z) * scaleFactor;
                    switch ((CollisionObjectType)tco.type)
                    {
                    case CollisionObjectType.ColSphere:
                        shape = new CollisionSphere(cp, cd.x);
                        break;

                    case CollisionObjectType.ColCylinder:
                        // We treat it as a capsule, but we raise the
                        // capsule up by the capRadius, and shorten
                        // the segment by the double the capRadius
                        Vector3 top = cp;
                        top.y += cd.y - cd.x * 2f;
                        cp.y  += cd.x;
                        shape  = new CollisionCapsule(cp, top, cd.x);
                        break;

                    case CollisionObjectType.ColBox:
                        Vector3 tp = cp;
                        tp.x -= cd.x * .5f;
                        tp.y -= cd.y * .5f;
                        shape = new CollisionAABB(tp, tp + cd);
                        break;
                    }
                    collisionAPI.AddCollisionShape(shape, handle);
                    tiles[tX, tZ]++;
                    objectsAdded++;

                    if (MO.DoLog)
                    {
                        MO.Log(string.Format(" tiles[{0},{1}] = {2}, tile at [{3},{4}] after adding shape {5}",
                                             tX, tZ, tiles[tX, tZ], tileX, tileZ, shape.ToString()));
                    }
                }
            }
        }
 public override CollisionShape Clone()
 {
     CollisionCapsule rv = new CollisionCapsule(bottomcenter, topcenter, capRadius);
     rv.handle = this.handle;
     rv.timeStamp = this.timeStamp;
     return rv;
 }
        public void ReadCapsule(string objectId, Matrix4 transform, XmlNode node, PhysicsData physicsData)
        {
            Quaternion rot = MathHelpers.GetRotation(transform);
            Matrix4 tmpTransform = rot.Inverse().ToRotationMatrix() * transform;
            Vector3 scaleDelta = tmpTransform.Scale - Vector3.UnitScale;
            if (scaleDelta.Length > PhysicsSerializer.ScaleEpsilon)
                log.Error("Scale is not currently supported for capsule shapes");
            float height = 0;
            float[] radius = new float[2];
            Vector3 halfExtents = Vector3.Zero;
            foreach (XmlNode childNode in node.ChildNodes) {
                switch (childNode.Name) {
                    case "height":
                        height = float.Parse(childNode.InnerText);
                        break;
                    case "radius": {
                            string[] values = childNode.InnerText.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
                            Debug.Assert(values.Length == 2);
                            for (int i = 0; i < 2; ++i)
                                radius[i] = float.Parse(values[i]);
                        }
                        break;
                    default:
                        DebugMessage(childNode);
                        break;
                }
            }
            // We only support capsules where the two radii match
            if (radius[0] != radius[1])
                log.Error("Different radii for capsules are not currently supported");
            Vector3 center = unitConversion * transform.Translation;
            Vector3 halfExtent = unitConversion * (.5f * height * (rot * Vector3.UnitY));
            radius[0] *= unitConversion;
            radius[1] *= unitConversion;

            CollisionShape collisionShape;
            collisionShape = new CollisionCapsule(center - halfExtent, center + halfExtent, radius[0]);
            physicsData.AddCollisionShape(objectId, collisionShape);
        }