Ejemplo n.º 1
0
        public override void SetTerrain(ITerrainChannel channel, short[] heightMap)
        {
            m_channel = channel;
            bool needToCreateHeightmapinODE = false;
            short[] _heightmap = ODETerrainHeightFieldHeights;
            if (ODETerrainHeightFieldHeights == null)
            {
                needToCreateHeightmapinODE = true; //We don't have any terrain yet, we need to generate one
                _heightmap = new short[((m_region.RegionSizeX + 3)*(m_region.RegionSizeY + 3))];
            }

            int heightmapWidth = m_region.RegionSizeX + 2;
            int heightmapHeight = m_region.RegionSizeY + 2;

            int heightmapWidthSamples = m_region.RegionSizeX + 3; // + one to complete the 256m + 2 margins each side
            int heightmapHeightSamples = m_region.RegionSizeY + 3;

            float hfmin = 2000;
            float hfmax = -2000;

            for (int x = 0; x < heightmapWidthSamples; x++)
            {
                for (int y = 0; y < heightmapHeightSamples; y++)
                {
                    //Some notes on this part
                    //xx and yy are used for the original heightmap, as we are offsetting the new one by 1
                    // so we subtract one so that we can put the heightmap in correctly
                    int xx = x - 1;
                    if (xx < 0)
                        xx = 0;
                    if (xx > m_region.RegionSizeX - 1)
                        xx = m_region.RegionSizeX - 1;
                    int yy = y - 1;
                    if (yy < 0)
                        yy = 0;
                    if (yy > m_region.RegionSizeY - 1)
                        yy = m_region.RegionSizeY - 1;

                    short val = heightMap[yy*m_region.RegionSizeX + xx];
                    //ODE is evil... flip x and y
                    _heightmap[(x*heightmapHeightSamples) + y] = val;

                    hfmin = (val < hfmin) ? val : hfmin;
                    hfmax = (val > hfmax) ? val : hfmax;
                }
            }

            needToCreateHeightmapinODE = true; //ODE seems to have issues with not rebuilding :(
            if (RegionTerrain != IntPtr.Zero)
            {
                d.SpaceRemove(space, RegionTerrain);
                d.GeomDestroy(RegionTerrain);
            }
            if (!needToCreateHeightmapinODE)
            {
                TerrainHeightFieldHeights = null;
                TerrainHeightFieldlimits = null;
                ODETerrainHeightFieldHeights = null;
                float[] heighlimits = new float[2];
                heighlimits[0] = hfmin;
                heighlimits[1] = hfmax;
                TerrainHeightFieldHeights = heightMap;
                TerrainHeightFieldlimits = heighlimits;
                ODETerrainHeightFieldHeights = _heightmap;
                return; //If we have already done this once, we don't need to do it again
            }
            lock (OdeLock)
            {
                const float scale = (1f/Constants.TerrainCompression);
                const float offset = 0.0f;
                float thickness = 0.01f;
                const int wrap = 0;

                IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
                GC.AddMemoryPressure(_heightmap.Length);
                    //Add the memory pressure properly (note: should we be doing this since we have it in managed memory?)
                //Do NOT copy it! Otherwise, it'll copy the terrain into unmanaged memory where we can't release it each time
                d.GeomHeightfieldDataBuildShort(HeightmapData, _heightmap, 0, heightmapHeight, heightmapWidth,
                                                heightmapHeightSamples, heightmapWidthSamples, scale,
                                                offset, thickness, wrap);

                d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1.0f, hfmax + 1.0f);
                RegionTerrain = d.CreateHeightfield(space, HeightmapData, 1);

                if (RegionTerrain != IntPtr.Zero)
                {
                    d.GeomSetCategoryBits(RegionTerrain, (int) (CollisionCategories.Land));
                    d.GeomSetCollideBits(RegionTerrain, (int) (CollisionCategories.Space));
                }

                NullObjectPhysicsActor terrainActor = new NullObjectPhysicsActor();

                actor_name_map[RegionTerrain] = terrainActor;

                d.Matrix3 R = new d.Matrix3();

                Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f);
                Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f);

                q1 = q1*q2;

                Vector3 v3;
                float angle;
                q1.GetAxisAngle(out v3, out angle);

                d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);

                d.GeomSetRotation(RegionTerrain, ref R);
                d.GeomSetPosition(RegionTerrain, (m_region.RegionSizeX*0.5f), (m_region.RegionSizeY*0.5f), 0);

                float[] heighlimits = new float[2];
                heighlimits[0] = hfmin;
                heighlimits[1] = hfmax;

                TerrainHeightFieldHeights = heightMap;
                ODETerrainHeightFieldHeights = _heightmap;
                TerrainHeightFieldlimits = heighlimits;
            }
        }
Ejemplo n.º 2
0
        public override void SetTerrain(ITerrainChannel channel, short[] heightMap)
        {
            m_channel = channel;
            float[] _heightmap = ODETerrainHeightFieldHeights;
            if (ODETerrainHeightFieldHeights == null)
                _heightmap = new float[m_region.RegionSizeX * m_region.RegionSizeY];
            
            for (int x = 0; x < m_region.RegionSizeX; x++)
            {
                for (int y = 0; y < m_region.RegionSizeY; y++)
                {
                    _heightmap[(x * m_region.RegionSizeX) + y] = heightMap[y * m_region.RegionSizeX + x] / Constants.TerrainCompression;
                }
            }

            float hfmin = _heightmap.Min();
            float hfmax = _heightmap.Max();

            SimulationChangesQueue.Enqueue(() =>
            {
                if (RegionTerrain != IntPtr.Zero)
                {
                    d.GeomHeightfieldDataDestroy(RegionTerrain);
                    d.SpaceRemove(space, RegionTerrain);
                    //d.GeomDestroy(RegionTerrain);
                    GC.RemoveMemoryPressure(_heightmap.Length);
                }

                const float scale = 1f;
                const float offset = 0.0f;
                float thickness = 0.2f;
                const int wrap = 0;

                IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
                GC.AddMemoryPressure(_heightmap.Length);
                //Add the memory pressure properly (note: should we be doing this since we have it in managed memory?)
                //Do NOT copy it! Otherwise, it'll copy the terrain into unmanaged memory where we can't release it each time
                d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, m_region.RegionSizeX, m_region.RegionSizeY,
                                                m_region.RegionSizeX, m_region.RegionSizeY, scale,
                                                offset, thickness, wrap);

                d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1.0f, hfmax + 1.0f);
                RegionTerrain = d.CreateHeightfield(space, HeightmapData, 1);

                d.GeomSetCategoryBits(RegionTerrain, (int)(CollisionCategories.Land));
                d.GeomSetCollideBits(RegionTerrain, (int)(CollisionCategories.Space));

                actor_name_map[RegionTerrain] = new NullObjectPhysicsActor();

                d.Matrix3 R = new d.Matrix3();

                Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f);
                Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f);

                q1 = q1 * q2;

                Vector3 v3;
                float angle;
                q1.GetAxisAngle(out v3, out angle);

                d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);

                d.GeomSetRotation(RegionTerrain, ref R);
                d.GeomSetPosition(RegionTerrain, (m_region.RegionSizeX * 0.5f), (m_region.RegionSizeY * 0.5f), 0);

                TerrainHeightFieldHeights = heightMap;
                ODETerrainHeightFieldHeights = _heightmap;
            });
            //Trimesh terrain
            /*var mesh = new OpenSim.Region.Physics.Meshing.Mesh(523452345);
            for (int i = 0; i < m_region.RegionSizeX - 1; i++)
            {
                for (int j = 0; j < m_region.RegionSizeY - 1; j++)
                {
                    mesh.Add(new Triangle(
                        new Vertex(i, j, m_channel[i, j]),
                        new Vertex(i + 1, j, m_channel[i + 1, j]),
                        new Vertex(i + 1, j  + 1, m_channel[i + 1, j + 1])));
                }
            }
            System.IntPtr vertices, indices;
            int vertexCount, indexCount;
            int vertexStride, triStride;
            mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
            // Note, that vertices are fixed in unmanaged heap
            mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
            // Also fixed, needs release after usage

            if (vertexCount == 0 || indexCount == 0)
                return;

            mesh.releaseSourceMeshData(); // free up the original mesh data to save memory
            var _triMeshData = d.GeomTriMeshDataCreate();

            d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount,
                                         triStride);
            d.GeomTriMeshDataPreprocess(_triMeshData);
            var RegionTerrain = d.CreateTriMesh(space, _triMeshData, null, null, null);

            d.GeomSetCategoryBits(RegionTerrain, (int)(CollisionCategories.Land));
            d.GeomSetCollideBits(RegionTerrain, (int)(CollisionCategories.Space));

            actor_name_map[RegionTerrain] = new NullObjectPhysicsActor();

            TerrainHeightFieldHeights = heightMap;*/
        }