28 using System.Collections.Generic;
31 using OpenSim.Framework;
32 using OpenSim.Region.Framework;
33 using OpenSim.Region.PhysicsModules.SharedBase;
40 namespace OpenSim.
Region.PhysicsModule.BulletS
44 static string LogHeader =
"[BULLETSIM TERRAIN MESH]";
46 private float[] m_savedHeightMap;
54 : base(physicsScene, regionBase, id)
59 : base(physicsScene, regionBase, id)
65 Vector3 minCoords, Vector3 maxCoords)
66 : base(physicsScene, regionBase, id)
73 m_savedHeightMap = initialMap;
75 m_sizeX = (int)(maxCoords.X - minCoords.X);
76 m_sizeY = (int)(maxCoords.Y - minCoords.Y);
78 bool meshCreationSuccess =
false;
79 if (BSParam.TerrainMeshMagnification == 1)
82 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh(m_physicsScene,
83 initialMap, m_sizeX, m_sizeY,
85 out indicesCount, out indices, out verticesCount, out vertices);
90 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh2(m_physicsScene,
91 initialMap, m_sizeX, m_sizeY,
92 BSParam.TerrainMeshMagnification,
93 physicsScene.TerrainManager.DefaultRegionSize,
95 out indicesCount, out indices, out verticesCount, out vertices);
97 if (!meshCreationSuccess)
100 m_physicsScene.DetailLog(
"{0},BSTerrainMesh.create,failedConversionOfHeightmap,id={1}", BSScene.DetailLogZero, ID);
101 m_physicsScene.Logger.ErrorFormat(
"{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase);
106 m_physicsScene.DetailLog(
"{0},BSTerrainMesh.create,meshed,id={1},indices={2},indSz={3},vertices={4},vertSz={5}",
107 BSScene.DetailLogZero, ID, indicesCount, indices.Length, verticesCount, vertices.Length);
109 m_terrainShape = m_physicsScene.PE.CreateMeshShape(m_physicsScene.World, indicesCount, indices, verticesCount, vertices);
110 if (!m_terrainShape.HasPhysicalShape)
113 m_physicsScene.DetailLog(
"{0},BSTerrainMesh.create,failedCreationOfShape,id={1}", BSScene.DetailLogZero, ID);
114 m_physicsScene.Logger.ErrorFormat(
"{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase);
119 Vector3 pos = regionBase;
120 Quaternion rot = Quaternion.Identity;
122 m_terrainBody = m_physicsScene.PE.CreateBodyWithDefaultMotionState(m_terrainShape, ID, pos, rot);
123 if (!m_terrainBody.HasPhysicalBody)
126 m_physicsScene.Logger.ErrorFormat(
"{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase);
130 physicsScene.PE.SetShapeCollisionMargin(m_terrainShape, BSParam.TerrainCollisionMargin);
133 m_physicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction);
134 m_physicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction);
135 m_physicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution);
136 m_physicsScene.PE.SetContactProcessingThreshold(m_terrainBody, BSParam.TerrainContactProcessingThreshold);
137 m_physicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT);
140 m_physicsScene.PE.SetMassProps(m_terrainBody, 0f, Vector3.Zero);
143 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_terrainBody);
146 m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_terrainBody);
148 m_terrainBody.collisionType = CollisionType.Terrain;
149 m_terrainBody.ApplyCollisionMask(m_physicsScene);
151 if (BSParam.UseSingleSidedMeshes)
153 m_physicsScene.DetailLog(
"{0},BSTerrainMesh.settingCustomMaterial,id={1}", BSScene.DetailLogZero, id);
154 m_physicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
158 m_physicsScene.PE.ForceActivationState(m_terrainBody, ActivationState.DISABLE_SIMULATION);
163 if (m_terrainBody.HasPhysicalBody)
165 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, m_terrainBody);
167 m_physicsScene.PE.DestroyObject(m_physicsScene.World, m_terrainBody);
168 m_terrainBody.Clear();
169 m_terrainShape.Clear();
177 float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
179 int mapIndex = (int)pos.Y * m_sizeY + (
int)pos.X;
182 ret = m_savedHeightMap[mapIndex];
187 m_physicsScene.Logger.WarnFormat(
"{0} Bad request for terrain height. terrainBase={1}, pos={2}",
188 LogHeader, TerrainBase, pos);
189 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
197 return m_physicsScene.SimpleWaterLevel;
203 float[] heightMap,
int sizeX,
int sizeY,
205 out
int indicesCountO, out
int[] indicesO,
206 out
int verticesCountO, out
float[] verticesO)
210 int indicesCount = 0;
211 int verticesCount = 0;
212 int[] indices =
new int[0];
213 float[] vertices =
new float[0];
226 int totalVertices = (sizeX + 1) * (sizeY + 1);
227 vertices =
new float[totalVertices * 3];
228 int totalIndices = sizeX * sizeY * 6;
229 indices =
new int[totalIndices];
231 if (physicsScene != null)
232 physicsScene.DetailLog(
"{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3}",
233 BSScene.DetailLogZero, totalVertices, totalIndices, extentBase);
234 float minHeight = float.MaxValue;
236 for (
int yy = 0; yy <= sizeY; yy++)
238 for (
int xx = 0; xx <= sizeX; xx++)
240 int offset = yy * sizeX + xx;
242 if (yy == sizeY) offset -= sizeX;
243 if (xx == sizeX) offset -= 1;
244 float height = heightMap[offset];
245 minHeight = Math.Min(minHeight, height);
246 vertices[verticesCount + 0] = (float)xx + extentBase.X;
247 vertices[verticesCount + 1] = (
float)yy + extentBase.Y;
248 vertices[verticesCount + 2] = height + extentBase.Z;
252 verticesCount = verticesCount / 3;
254 for (
int yy = 0; yy < sizeY; yy++)
256 for (
int xx = 0; xx < sizeX; xx++)
258 int offset = yy * (sizeX + 1) + xx;
260 indices[indicesCount + 0] = offset;
261 indices[indicesCount + 1] = offset + 1;
262 indices[indicesCount + 2] = offset + sizeX + 1;
263 indices[indicesCount + 3] = offset + 1;
264 indices[indicesCount + 4] = offset + sizeX + 2;
265 indices[indicesCount + 5] = offset + sizeX + 1;
274 if (physicsScene != null)
275 physicsScene.Logger.ErrorFormat(
"{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}",
276 LogHeader, physicsScene.RegionName, extentBase, e);
279 indicesCountO = indicesCount;
281 verticesCountO = verticesCount;
282 verticesO = vertices;
287 private class HeightMapGetter
289 private float[] m_heightMap;
292 public HeightMapGetter(
float[] pHeightMap,
int pSizeX,
int pSizeY)
294 m_heightMap = pHeightMap;
299 public float GetHeight(
int xx,
int yy)
305 offset = (m_sizeY - 1) * m_sizeX + (m_sizeX - 1);
307 offset = (m_sizeY - 1) * m_sizeX + xx;
310 offset = yy * m_sizeX + (m_sizeX - 1);
312 offset = yy * m_sizeX + xx;
314 return m_heightMap[offset];
322 float[] heightMap,
int sizeX,
int sizeY,
326 out
int indicesCountO, out
int[] indicesO,
327 out
int verticesCountO, out
float[] verticesO)
331 int indicesCount = 0;
332 int verticesCount = 0;
333 int[] indices =
new int[0];
334 float[] vertices =
new float[0];
336 HeightMapGetter hmap =
new HeightMapGetter(heightMap, sizeX, sizeY);
339 int meshX = sizeX * magnification;
340 int meshY = sizeY * magnification;
342 float meshXStep = extent.X / meshX;
343 float meshYStep = extent.Y / meshY;
353 int totalVertices = (meshX + 1) * (meshY + 1);
354 vertices =
new float[totalVertices * 3];
355 int totalIndices = meshX * meshY * 6;
356 indices =
new int[totalIndices];
358 if (physicsScene != null)
359 physicsScene.DetailLog(
"{0},BSTerrainMesh.ConvertHeightMapToMesh2,inSize={1},outSize={2},totVert={3},totInd={4},extentBase={5}",
360 BSScene.DetailLogZero,
new Vector2(sizeX, sizeY),
new Vector2(meshX, meshY),
361 totalVertices, totalIndices, extentBase);
363 float minHeight = float.MaxValue;
366 for (
int yy = 0; yy <= meshY; yy++)
368 for (
int xx = 0; xx <= meshX; xx++)
370 float offsetY = (float)yy * (
float)sizeY / (float)meshY;
371 int stepY = (int)offsetY;
372 float fractionalY = offsetY - (float)stepY;
373 float offsetX = (float)xx * (
float)sizeX / (float)meshX;
374 int stepX = (int)offsetX;
375 float fractionalX = offsetX - (float)stepX;
381 float heightUL = hmap.GetHeight(stepX , stepY );
382 float heightUR = hmap.GetHeight(stepX + 1, stepY );
383 float heightLL = hmap.GetHeight(stepX , stepY + 1);
384 float heightLR = hmap.GetHeight(stepX + 1, stepY + 1);
387 float height = heightUL * (1 - fractionalX) * (1 - fractionalY)
388 + heightUR * fractionalX * (1 - fractionalY)
389 + heightLL * (1 - fractionalX) * fractionalY
390 + heightLR * fractionalX * fractionalY;
395 minHeight = Math.Min(minHeight, height);
397 vertices[verticesCount + 0] = (float)xx * meshXStep + extentBase.X;
398 vertices[verticesCount + 1] = (
float)yy * meshYStep + extentBase.Y;
399 vertices[verticesCount + 2] = height + extentBase.Z;
407 for (
int yy = 0; yy < meshY; yy++)
409 for (
int xx = 0; xx < meshX; xx++)
411 int offset = yy * (meshX + 1) + xx;
413 indices[indicesCount + 0] = offset;
414 indices[indicesCount + 1] = offset + 1;
415 indices[indicesCount + 2] = offset + meshX + 1;
416 indices[indicesCount + 3] = offset + 1;
417 indices[indicesCount + 4] = offset + meshX + 2;
418 indices[indicesCount + 5] = offset + meshX + 1;
427 if (physicsScene != null)
428 physicsScene.Logger.ErrorFormat(
"{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}",
429 LogHeader, physicsScene.RegionName, extentBase, e);
432 indicesCountO = indicesCount;
434 verticesCountO = verticesCount;
435 verticesO = vertices;
BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
static bool ConvertHeightmapToMesh(BSScene physicsScene, float[] heightMap, int sizeX, int sizeY, Vector3 extentBase, out int indicesCountO, out int[] indicesO, out int verticesCountO, out float[] verticesO)
override float GetTerrainHeightAtXYZ(Vector3 pos)
BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id)
override float GetWaterLevelAtXYZ(Vector3 pos)
static bool ConvertHeightmapToMesh2(BSScene physicsScene, float[] heightMap, int sizeX, int sizeY, int magnification, Vector3 extent, Vector3 extentBase, out int indicesCountO, out int[] indicesO, out int verticesCountO, out float[] verticesO)
BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, Vector3 minCoords, Vector3 maxCoords)