コード例 #1
0
        ////////////////////////////////////////////////////////////////////////////////
        //
        //	TerrainDemo -- private helper methods
        //
        ////////////////////////////////////////////////////////////////////////////////

        /// called whenever key terrain attribute is changed
        public override void ClientResetScene()
        {
            base.ClientResetScene();
            // remove old heightfield
            m_rawHeightfieldData = null;

            // reset gravity to point in appropriate direction
            //m_dynamicsWorld.setGravity(getUpVector(m_upAxis, 0.0f, -s_gravity));
            m_dynamicsWorld.SetGravity(ref m_defaultGravity);

            // get new heightfield of appropriate type
            m_rawHeightfieldData =
                GetRawHeightfieldData(m_model, m_type, ref m_minHeight, ref m_maxHeight);
            Debug.Assert(m_rawHeightfieldData != null, "failed to create raw heightfield");

            if (m_terrainRigidBody != null)
            {
                m_dynamicsWorld.RemoveCollisionObject(m_terrainRigidBody);
                m_terrainRigidBody = null;
                m_terrainShape     = null;
                m_collisionShapes.Remove(m_terrainShape);
            }

            bool flipQuadEdges = false;

            m_terrainShape =
                new HeightfieldTerrainShape(s_gridSize, s_gridSize,
                                            m_rawHeightfieldData,
                                            s_gridHeightScale,
                                            m_minHeight, m_maxHeight,
                                            m_upAxis, m_type, flipQuadEdges);
            Debug.Assert(m_terrainShape != null, "null heightfield");

            // scale the shape
            IndexedVector3 localScaling = GetUpVector(m_upAxis, s_gridSpacing, 1.0f);

            m_terrainShape.SetLocalScaling(ref localScaling);

            // stash this shape away
            m_collisionShapes.Add(m_terrainShape);

            // set origin to middle of heightfield
            IndexedMatrix tr = IndexedMatrix.CreateTranslation(new IndexedVector3(0, -20, 0));

            // create ground object
            float mass = 0.0f;

            m_terrainRigidBody = LocalCreateRigidBody(mass, ref tr, m_terrainShape);

            CollisionShape sphere = new SphereShape(0.5f);

            tr = IndexedMatrix.CreateTranslation(new IndexedVector3(0, 0, 0));

            LocalCreateRigidBody(1f, ref tr, sphere);
        }
        private HeightfieldTerrainShape _CreateTerrainShape()
        {
            Terrain t = GetComponent <Terrain>();

            if (t == null)
            {
                Debug.LogError("Needs to be attached to a game object with a Terrain component." + name);
                return(null);
            }

            BTerrainCollisionObject tco = GetComponent <BTerrainCollisionObject>();

            if (tco == null)
            {
                Debug.LogError("Needs to be attached to a game object with a BTerrainCollisionObject." + name);
            }

            TerrainData td        = t.terrainData;
            int         width     = td.heightmapWidth;
            int         length    = td.heightmapHeight;
            float       maxHeight = td.size.y;

            //generate procedural data
            byte[] terr = new byte[width * length * sizeof(float)];
            System.IO.MemoryStream file   = new System.IO.MemoryStream(terr);
            System.IO.BinaryWriter writer = new System.IO.BinaryWriter(file);

            for (int i = 0; i < length; i++)
            {
                float[,] row = td.GetHeights(0, i, width, 1);
                for (int j = 0; j < width; j++)
                {
                    writer.Write(row[0, j] * maxHeight);
                }
            }

            writer.Flush();
            file.Position = 0;

            pinnedTerrainData = GCHandle.Alloc(terr, GCHandleType.Pinned);

            HeightfieldTerrainShape hs = new HeightfieldTerrainShape(width, length, pinnedTerrainData.AddrOfPinnedObject(), 1f, 0f, maxHeight, upIndex, scalarType, false);

            hs.SetUseDiamondSubdivision(true);
            hs.LocalScaling = new BulletSharp.Math.Vector3(td.heightmapScale.x, 1f, td.heightmapScale.z);
            //just allocated several hundred float arrays. Garbage collect now since 99% likely we just loaded the scene
            GC.Collect();

            return(hs);
        }
コード例 #3
0
        private void CreateHeightfieldTerrain()
        {
            const float         minHeight = 0;
            const float         maxHeight = 10.0f;
            const float         heightScale = maxHeight / 256.0f;
            const int           width = 64, length = 64;
            const int           dataLength = width * length * sizeof(float);
            const PhyScalarType scalarType = PhyScalarType.Single;

            var scale = new Vector3(15.0f, maxHeight, 15.0f);

            _terrainData = Marshal.AllocHGlobal(dataLength);
            var terrain = new byte[dataLength];

            using (var file = new MemoryStream(terrain))
            {
                using (var writer = new BinaryWriter(file))
                {
                    for (int i = 0; i < width; i++)
                    {
                        for (int j = 0; j < length; j++)
                        {
                            writer.Write((float)((maxHeight / 2) + 4 * Math.Sin(j * 0.5f) * Math.Cos(i)));
                        }
                    }
                }
            }

            Marshal.Copy(terrain, 0, _terrainData, terrain.Length);

            var groundShape = new HeightfieldTerrainShape(width, length,
                                                          _terrainData, heightScale, minHeight, maxHeight, upIndex, scalarType, false);

            groundShape.SetUseDiamondSubdivision(true);
            groundShape.LocalScaling = new Vector3(scale.X, 1, scale.Z);

            Matrix transform = Matrix.Translation(-scale.X / 2, scale.Y / 2, -scale.Z / 2);

            RigidBody ground = PhysicsHelper.CreateStaticBody(transform, groundShape, World);

            ground.UserObject = "Ground";

            Matrix vehicleTransform = Matrix.Translation(new Vector3(20, 3, -3));

            CreateVehicle(vehicleTransform);
        }
コード例 #4
0
        private void CreateHeightfieldTerrainFromFile()
        {
            const float         minHeight = 0;
            const float         maxHeight = 10.0f;
            const float         heightScale = maxHeight / 256.0f;
            const int           width = 128, length = 128;
            const int           dataLength = width * length * sizeof(byte);
            const PhyScalarType scalarType = PhyScalarType.Byte;

            var scale = new Vector3(5.0f, maxHeight, 5.0f);

            string heightfieldFile = Path.Combine("data", "heightfield128x128.raw");

            _terrainData = Marshal.AllocHGlobal(dataLength);

            using (var stream = new FileStream(heightfieldFile, FileMode.Open, FileAccess.Read))
            {
                using (var reader = new BinaryReader(stream))
                {
                    while (stream.Position < stream.Length)
                    {
                        int  offset = (int)stream.Position;
                        byte height = reader.ReadByte();
                        Marshal.WriteByte(_terrainData, offset, height);
                    }
                }
            }

            var shape = new HeightfieldTerrainShape(width, length,
                                                    _terrainData, heightScale, minHeight, maxHeight, upIndex, scalarType, false);

            shape.SetUseDiamondSubdivision(true);
            shape.LocalScaling = new Vector3(scale.X, 1, scale.Z);

            Matrix transform = Matrix.Translation(-scale.X / 2, scale.Y / 2, -scale.Z / 2);

            RigidBody ground = PhysicsHelper.CreateStaticBody(transform, shape, World);

            ground.UserObject = "Ground";

            Matrix vehicleTransform = Matrix.Translation(new Vector3(20, 3, -3));

            CreateVehicle(vehicleTransform);
        }
コード例 #5
0
        protected override CollisionShape CreateShape()
        {
            if (this.ms == null)
            {
                byte[] terr = new byte[this.w * this.l * 4];
                ms = new MemoryStream(terr);
                BinaryWriter writer = new BinaryWriter(ms);
                for (int i = 0; i < this.w * this.l; i++)
                {
                    writer.Write(this.h[i]);
                }
                writer.Flush();
            }
            ms.Position = 0;
            HeightfieldTerrainShape hs = new HeightfieldTerrainShape(w, l, ms, 0.0f, minh, maxh, 1, PhyScalarType.PhyFloat, false);

            hs.SetUseDiamondSubdivision(true);
            //hs.LocalScaling = new Vector3(this.sx, 1.0f, this.sz);
            return(hs);
        }
コード例 #6
0
ファイル: AndrewDemo.cs プロジェクト: superowner/bullet-xna
        public virtual void LoadHeightField(float[,] heights, float heightRange, uint vertsX, uint vertsZ, Vector3 loc, int metersPerSample)
        {
            //if (worldLoaded == false || metersPerSample > 2)
            //    return;
            loc = loc / scaleFactor;
            //heightRange = heightRange * 1000;
            //loc.X += heightFieldOffset;
            //loc.z += heightFieldOffset; // these axes are out by about 1m?
            if (heightFields.ContainsKey(loc))
            {
                int oldMetersPerSample = heightFields[loc];
                if (oldMetersPerSample == metersPerSample)
                {
                    return; // no need to update
                }
                else
                {
                    // we need to delete the old one to rebuild this one
                    foreach (CollisionObject a in m_dynamicsWorld.GetCollisionObjectArray())
                    {
                        if (a.GetCollisionShape() != null && a.GetCollisionShape().GetShapeType() == BroadphaseNativeTypes.TERRAIN_SHAPE_PROXYTYPE)
                        {
                            string terrainName = (string)a.GetUserPointer();
                            if (terrainName == "TestHeightField_" + loc)
                            {
                                a.Cleanup();
                                heightFields.Remove(loc);
                                System.Console.WriteLine("Removed heightmap at position '{0}' with metersPerSample: '{1}' and old: '{2}'",
                                                         loc, metersPerSample, oldMetersPerSample);
                                break;
                            }
                        }
                    }
                }
            }
            byte[]       terr   = new byte[vertsX * vertsZ * 4];
            MemoryStream file   = new MemoryStream(terr);
            BinaryWriter writer = new BinaryWriter(file);

            for (int i = 0; i < vertsX; i++)
            {
                for (int j = 0; j < vertsZ; j++)
                {
                    writer.Write((float)((heightRange / 2) + 4 * Math.Sin(j * 0.5f) * Math.Cos(i)));
                    //writer.Write(0f);
                }
            }
            writer.Flush();
            file.Position = 0;
            float              heightScale       = heightRange / 32767f / scaleFactor;
            int                upAxis            = 1;
            CollisionShape     terrainShape      = new HeightfieldTerrainShape((int)vertsX, (int)vertsZ, terr, heightScale, 0, heightRange, upAxis, PHY_ScalarType.PHY_FLOAT, true);
            IndexedMatrix      worldTransform    = IndexedMatrix.CreateTranslation(loc);
            DefaultMotionState objectMotionState = new DefaultMotionState(worldTransform, IndexedMatrix.Identity);

            //terrainShape = new StaticPlaneShape(Vector3.Up, 0f);
            //IndexedVector3 halfExtents = new IndexedVector3(50, 50, 50);

            //terrainShape = new BoxShape(ref halfExtents);

            RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(0, objectMotionState, terrainShape);
            RigidBody terrain = new RigidBody(rbInfo);


            //IndexedMatrix groundTransform = IndexedMatrix.CreateTranslation(new IndexedVector3(0, -50, 0));
            IndexedMatrix groundTransform = IndexedMatrix.CreateTranslation(new IndexedVector3(0, -5, 0));

            LocalCreateRigidBody(0f, groundTransform, terrainShape);

            terrain.SetUserPointer("TestHeightField_" + loc.ToString());
            //terrain.SetCollisionFlags(CollisionFlags.CF_KINEMATIC_OBJECT);
            ////m_dynamicsWorld.AddCollisionObject(terrain, CollisionFilterGroups.DefaultFilter, CollisionFilterGroups.AllFilter);
            //m_dynamicsWorld.AddCollisionObject(terrain);


            System.Console.WriteLine("Added heightmap at position: '{0}' with metersPerSample: '{1}'", loc, metersPerSample);
            heightFields.Add(loc, metersPerSample);
        }
コード例 #7
0
        public Physics(VehicleDemo game)
        {
            CollisionShape groundShape = new BoxShape(50, 3, 50);

            CollisionShapes.Add(groundShape);

            CollisionConf = new DefaultCollisionConfiguration();
            Dispatcher    = new CollisionDispatcher(CollisionConf);
            Solver        = new SequentialImpulseConstraintSolver();

            Vector3 worldMin = new Vector3(-10000, -10000, -10000);
            Vector3 worldMax = new Vector3(10000, 10000, 10000);

            Broadphase = new AxisSweep3(worldMin, worldMax);
            //Broadphase = new DbvtBroadphase();

            World = new DiscreteDynamicsWorld(Dispatcher, Broadphase, Solver, CollisionConf);

            int    i;
            Matrix tr;
            Matrix vehicleTr;

            if (UseTrimeshGround)
            {
                const float scale = 20.0f;

                //create a triangle-mesh ground
                int vertStride  = Vector3.SizeInBytes;
                int indexStride = 3 * sizeof(int);

                const int NUM_VERTS_X = 20;
                const int NUM_VERTS_Y = 20;
                const int totalVerts  = NUM_VERTS_X * NUM_VERTS_Y;

                const int totalTriangles = 2 * (NUM_VERTS_X - 1) * (NUM_VERTS_Y - 1);

                TriangleIndexVertexArray vertexArray = new TriangleIndexVertexArray();
                IndexedMesh mesh = new IndexedMesh();
                mesh.Allocate(totalVerts, vertStride, totalTriangles, indexStride, PhyScalarType.Int32, PhyScalarType.Single);

                BulletSharp.DataStream data = mesh.LockVerts();
                for (i = 0; i < NUM_VERTS_X; i++)
                {
                    for (int j = 0; j < NUM_VERTS_Y; j++)
                    {
                        float wl     = .2f;
                        float height = 20.0f * (float)(Math.Sin(i * wl) * Math.Cos(j * wl));

                        data.Write((i - NUM_VERTS_X * 0.5f) * scale);
                        data.Write(height);
                        data.Write((j - NUM_VERTS_Y * 0.5f) * scale);
                    }
                }

                int      index = 0;
                IntArray idata = mesh.TriangleIndices;
                for (i = 0; i < NUM_VERTS_X - 1; i++)
                {
                    for (int j = 0; j < NUM_VERTS_Y - 1; j++)
                    {
                        idata[index++] = j * NUM_VERTS_X + i;
                        idata[index++] = j * NUM_VERTS_X + i + 1;
                        idata[index++] = (j + 1) * NUM_VERTS_X + i + 1;

                        idata[index++] = j * NUM_VERTS_X + i;
                        idata[index++] = (j + 1) * NUM_VERTS_X + i + 1;
                        idata[index++] = (j + 1) * NUM_VERTS_X + i;
                    }
                }

                vertexArray.AddIndexedMesh(mesh);
                groundShape = new BvhTriangleMeshShape(vertexArray, true);

                tr        = Matrix.Identity;
                vehicleTr = Matrix.Translation(0, -2, 0);
            }
            else
            {
                // Use HeightfieldTerrainShape

                int width = 40, length = 40;
                //int width = 128, length = 128; // Debugging is too slow for this
                float   maxHeight   = 10.0f;
                float   heightScale = maxHeight / 256.0f;
                Vector3 scale       = new Vector3(20.0f, maxHeight, 20.0f);

                //PhyScalarType scalarType = PhyScalarType.PhyUChar;
                //FileStream file = new FileStream(heightfieldFile, FileMode.Open, FileAccess.Read);

                // Use float data
                PhyScalarType scalarType = PhyScalarType.Single;
                byte[]        terr       = new byte[width * length * 4];
                MemoryStream  file       = new MemoryStream(terr);
                BinaryWriter  writer     = new BinaryWriter(file);
                for (i = 0; i < width; i++)
                {
                    for (int j = 0; j < length; j++)
                    {
                        writer.Write((float)((maxHeight / 2) + 4 * Math.Sin(j * 0.5f) * Math.Cos(i)));
                    }
                }
                writer.Flush();
                file.Position = 0;

                HeightfieldTerrainShape heightterrainShape = new HeightfieldTerrainShape(width, length,
                                                                                         file, heightScale, 0, maxHeight, upIndex, scalarType, false);
                heightterrainShape.SetUseDiamondSubdivision(true);

                groundShape = heightterrainShape;
                groundShape.LocalScaling = new Vector3(scale.X, 1, scale.Z);

                tr        = Matrix.Translation(new Vector3(-scale.X / 2, scale.Y / 2, -scale.Z / 2));
                vehicleTr = Matrix.Translation(new Vector3(20, 3, -3));


                // Create graphics object

                file.Position = 0;
                BinaryReader reader = new BinaryReader(file);

                int totalTriangles = (width - 1) * (length - 1) * 2;
                int totalVerts     = width * length;

                game.groundMesh = new Mesh(game.Device, totalTriangles, totalVerts,
                                           MeshFlags.SystemMemory | MeshFlags.Use32Bit, VertexFormat.Position | VertexFormat.Normal);
                SlimDX.DataStream data = game.groundMesh.LockVertexBuffer(LockFlags.None);
                for (i = 0; i < width; i++)
                {
                    for (int j = 0; j < length; j++)
                    {
                        float height;
                        if (scalarType == PhyScalarType.Single)
                        {
                            // heightScale isn't applied internally for float data
                            height = reader.ReadSingle();
                        }
                        else if (scalarType == PhyScalarType.Byte)
                        {
                            height = file.ReadByte() * heightScale;
                        }
                        else
                        {
                            height = 0.0f;
                        }

                        data.Write((j - length * 0.5f) * scale.X);
                        data.Write(height);
                        data.Write((i - width * 0.5f) * scale.Z);

                        // Normals will be calculated later
                        data.Position += 12;
                    }
                }
                game.groundMesh.UnlockVertexBuffer();
                file.Close();

                data = game.groundMesh.LockIndexBuffer(LockFlags.None);
                for (i = 0; i < width - 1; i++)
                {
                    for (int j = 0; j < length - 1; j++)
                    {
                        // Using diamond subdivision
                        if ((j + i) % 2 == 0)
                        {
                            data.Write(j * width + i);
                            data.Write((j + 1) * width + i + 1);
                            data.Write(j * width + i + 1);

                            data.Write(j * width + i);
                            data.Write((j + 1) * width + i);
                            data.Write((j + 1) * width + i + 1);
                        }
                        else
                        {
                            data.Write(j * width + i);
                            data.Write((j + 1) * width + i);
                            data.Write(j * width + i + 1);

                            data.Write(j * width + i + 1);
                            data.Write((j + 1) * width + i);
                            data.Write((j + 1) * width + i + 1);
                        }

                        /*
                         * // Not using diamond subdivision
                         * data.Write(j * width + i);
                         * data.Write((j + 1) * width + i);
                         * data.Write(j * width + i + 1);
                         *
                         * data.Write(j * width + i + 1);
                         * data.Write((j + 1) * width + i);
                         * data.Write((j + 1) * width + i + 1);
                         */
                    }
                }
                game.groundMesh.UnlockIndexBuffer();

                game.groundMesh.ComputeNormals();
            }

            CollisionShapes.Add(groundShape);


            //create ground object
            RigidBody ground = LocalCreateRigidBody(0, tr, groundShape);

            ground.UserObject = "Ground";


            CollisionShape chassisShape = new BoxShape(1.0f, 0.5f, 2.0f);

            CollisionShapes.Add(chassisShape);

            CompoundShape compound = new CompoundShape();

            CollisionShapes.Add(compound);

            //localTrans effectively shifts the center of mass with respect to the chassis
            Matrix localTrans = Matrix.Translation(Vector3.UnitY);

            compound.AddChildShape(localTrans, chassisShape);
            RigidBody carChassis = LocalCreateRigidBody(800, Matrix.Identity, compound);

            carChassis.UserObject = "Chassis";
            //carChassis.SetDamping(0.2f, 0.2f);

            //CylinderShapeX wheelShape = new CylinderShapeX(wheelWidth, wheelRadius, wheelRadius);


            // clientResetScene();

            // create vehicle
            RaycastVehicle.VehicleTuning tuning           = new RaycastVehicle.VehicleTuning();
            IVehicleRaycaster            vehicleRayCaster = new DefaultVehicleRaycaster(World);

            vehicle = new RaycastVehicle(tuning, carChassis, vehicleRayCaster);

            carChassis.ActivationState = ActivationState.DisableDeactivation;
            World.AddAction(vehicle);


            float connectionHeight = 1.2f;
            bool  isFrontWheel     = true;

            // choose coordinate system
            vehicle.SetCoordinateSystem(rightIndex, upIndex, forwardIndex);

            Vector3   connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius);
            WheelInfo a = vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel);

            connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius);
            vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel);

            isFrontWheel       = false;
            connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius);
            vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel);

            connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius);
            vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel);


            for (i = 0; i < vehicle.NumWheels; i++)
            {
                WheelInfo wheel = vehicle.GetWheelInfo(i);
                wheel.SuspensionStiffness      = suspensionStiffness;
                wheel.WheelsDampingRelaxation  = suspensionDamping;
                wheel.WheelsDampingCompression = suspensionCompression;
                wheel.FrictionSlip             = wheelFriction;
                wheel.RollInfluence            = rollInfluence;
            }

            vehicle.RigidBody.WorldTransform = vehicleTr;
        }
コード例 #8
0
 private static Vector3[] CreateHeightFieldTerrainShape(HeightfieldTerrainShape heightfieldTerrainShape, out uint[] indices)
 {
     // HeightfieldTerrainShape does not expose its data
     indices = null;
     return(new Vector3[1]);
 }