aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin
diff options
context:
space:
mode:
authorRobert Adams2012-08-31 11:33:36 -0700
committerRobert Adams2012-08-31 11:41:33 -0700
commitffdc7987207de279116a077e2042ed3a1f381a5f (patch)
treebe0a30b79da8abf96ba826e370c62457658fda84 /OpenSim/Region/Physics/BulletSPlugin
parentBulletSim: clean up some variable naming for consistancy. (diff)
downloadopensim-SC-ffdc7987207de279116a077e2042ed3a1f381a5f.zip
opensim-SC-ffdc7987207de279116a077e2042ed3a1f381a5f.tar.gz
opensim-SC-ffdc7987207de279116a077e2042ed3a1f381a5f.tar.bz2
opensim-SC-ffdc7987207de279116a077e2042ed3a1f381a5f.tar.xz
BulletSim: Update BulletSimAPI to match the DLL interface.
Major rework of terrain management which finally makes mega-regions work. Update heightmap of terrain by rebuilding the terrain's body and shape. There is a problem with just replacing the shape so this workaround will do for the moment but it will need to be resolved for mesh and hull switching.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs2
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs356
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs8
4 files changed, 231 insertions, 137 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index fa21233..747ae71 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -228,7 +228,7 @@ public class BSCharacter : BSPhysObject
228 float terrainHeight = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); 228 float terrainHeight = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position);
229 if (Position.Z < terrainHeight) 229 if (Position.Z < terrainHeight)
230 { 230 {
231 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); 231 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
232 _position.Z = terrainHeight + 2.0f; 232 _position.Z = terrainHeight + 2.0f;
233 ret = true; 233 ret = true;
234 } 234 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 2f55ba4..4a468af 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -1070,7 +1070,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1070 (s) => { return s.m_params[0].terrainRestitution; }, 1070 (s) => { return s.m_params[0].terrainRestitution; },
1071 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), 1071 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
1072 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 1072 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
1073 0.5f, 1073 0.2f,
1074 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, 1074 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
1075 (s) => { return s.m_params[0].avatarFriction; }, 1075 (s) => { return s.m_params[0].avatarFriction; },
1076 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ), 1076 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index 733d9c2..ab45f8f 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -54,17 +54,19 @@ public class BSTerrainManager
54 // amount to make sure that a bounding box is built for the terrain. 54 // amount to make sure that a bounding box is built for the terrain.
55 public const float HEIGHT_EQUAL_FUDGE = 0.2f; 55 public const float HEIGHT_EQUAL_FUDGE = 0.2f;
56 56
57 public const float TERRAIN_COLLISION_MARGIN = 0.2f; 57 public const float TERRAIN_COLLISION_MARGIN = 0.0f;
58
59 // Until the whole simulator is changed to pass us the region size, we rely on constants.
60 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, 0f);
58 61
59 // The scene that I am part of 62 // The scene that I am part of
60 BSScene m_physicsScene; 63 private BSScene m_physicsScene;
61 64
62 // The ground plane created to keep thing from falling to infinity. 65 // The ground plane created to keep thing from falling to infinity.
63 private BulletBody m_groundPlane; 66 private BulletBody m_groundPlane;
64 67
65 // If doing mega-regions, if we're region zero we will be managing multiple 68 // If doing mega-regions, if we're region zero we will be managing multiple
66 // region terrains since region zero does the physics for the whole mega-region. 69 // region terrains since region zero does the physics for the whole mega-region.
67 private Dictionary<Vector2, BulletBody> m_terrains;
68 private Dictionary<Vector2, BulletHeightMapInfo> m_heightMaps; 70 private Dictionary<Vector2, BulletHeightMapInfo> m_heightMaps;
69 71
70 // True of the terrain has been modified. 72 // True of the terrain has been modified.
@@ -78,16 +80,22 @@ public class BSTerrainManager
78 80
79 // If doing mega-regions, this holds our offset from region zero of 81 // If doing mega-regions, this holds our offset from region zero of
80 // the mega-regions. "parentScene" points to the PhysicsScene of region zero. 82 // the mega-regions. "parentScene" points to the PhysicsScene of region zero.
81 private Vector3 m_worldOffset = Vector3.Zero; 83 private Vector3 m_worldOffset;
82 public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize); 84 // If the parent region (region 0), this is the extent of the combined regions
83 private PhysicsScene m_parentScene = null; 85 // relative to the origin of region zero
86 private Vector3 m_worldMax;
87 private PhysicsScene m_parentScene;
84 88
85 public BSTerrainManager(BSScene physicsScene) 89 public BSTerrainManager(BSScene physicsScene)
86 { 90 {
87 m_physicsScene = physicsScene; 91 m_physicsScene = physicsScene;
88 m_terrains = new Dictionary<Vector2,BulletBody>();
89 m_heightMaps = new Dictionary<Vector2,BulletHeightMapInfo>(); 92 m_heightMaps = new Dictionary<Vector2,BulletHeightMapInfo>();
90 m_terrainModified = false; 93 m_terrainModified = false;
94
95 // Assume one region of default size
96 m_worldOffset = Vector3.Zero;
97 m_worldMax = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, 4096f);
98 m_parentScene = null;
91 } 99 }
92 100
93 // Create the initial instance of terrain and the underlying ground plane. 101 // Create the initial instance of terrain and the underlying ground plane.
@@ -95,7 +103,7 @@ public class BSTerrainManager
95 // by the managed code. 103 // by the managed code.
96 // The terrains and the groundPlane are not added to the list of PhysObjects. 104 // The terrains and the groundPlane are not added to the list of PhysObjects.
97 // This is called from the initialization routine so we presume it is 105 // This is called from the initialization routine so we presume it is
98 // safe to call Bullet in real time. We hope no one is moving around prim yet. 106 // safe to call Bullet in real time. We hope no one is moving prims around yet.
99 public void CreateInitialGroundPlaneAndTerrain() 107 public void CreateInitialGroundPlaneAndTerrain()
100 { 108 {
101 // The ground plane is here to catch things that are trying to drop to negative infinity 109 // The ground plane is here to catch things that are trying to drop to negative infinity
@@ -105,125 +113,91 @@ public class BSTerrainManager
105 BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr); 113 BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
106 114
107 Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE); 115 Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE);
108 Vector3 maxTerrainCoords = new Vector3(Constants.RegionSize, Constants.RegionSize, HEIGHT_INITIALIZATION); 116 Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION);
109 int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; 117 int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y;
110 float[] initialMap = new float[totalHeights]; 118 float[] initialMap = new float[totalHeights];
111 for (int ii = 0; ii < totalHeights; ii++) 119 for (int ii = 0; ii < totalHeights; ii++)
112 { 120 {
113 initialMap[ii] = HEIGHT_INITIALIZATION; 121 initialMap[ii] = HEIGHT_INITIALIZATION;
114 } 122 }
115 CreateNewTerrainSegment(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords); 123 UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true);
116 } 124 }
117 125
126 // Release all the terrain structures we might have allocated
118 public void ReleaseGroundPlaneAndTerrain() 127 public void ReleaseGroundPlaneAndTerrain()
119 { 128 {
120 if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr)) 129 if (m_groundPlane.Ptr != IntPtr.Zero)
121 { 130 {
122 BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, m_groundPlane.Ptr); 131 if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr))
123 }
124 m_groundPlane.Ptr = IntPtr.Zero;
125
126 foreach (KeyValuePair<Vector2, BulletBody> kvp in m_terrains)
127 {
128 if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.Ptr))
129 { 132 {
130 BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.Ptr); 133 BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
131 BulletSimAPI.ReleaseHeightMapInfo2(m_heightMaps[kvp.Key].Ptr);
132 } 134 }
135 m_groundPlane.Ptr = IntPtr.Zero;
133 } 136 }
134 m_terrains.Clear(); 137
135 m_heightMaps.Clear(); 138 ReleaseTerrain();
136 } 139 }
137 140
138 // Create a new terrain description. This is used for mega-regions where 141 // Release all the terrain we have allocated
139 // the children of region zero give region zero all of the terrain 142 public void ReleaseTerrain()
140 // segments since region zero does all the physics for the mega-region.
141 // Call at taint time!!
142 public void CreateNewTerrainSegment(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
143 { 143 {
144 // The Z coordinates are recalculated to be the min and max height of the terrain 144 foreach (KeyValuePair<Vector2, BulletHeightMapInfo> kvp in m_heightMaps)
145 // itself. The caller may have passed us the real region extent.
146 float minZ = float.MaxValue;
147 float maxZ = float.MinValue;
148 int hSize = heightMap.Length;
149 for (int ii = 0; ii < hSize; ii++)
150 { 145 {
151 float height = heightMap[ii]; 146 if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr))
152 if (height < minZ) minZ = height; 147 {
153 if (height > maxZ) maxZ = height; 148 BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr);
149 BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr);
150 }
154 } 151 }
155 // If the terrain is flat, make a difference so we get a bounding box 152 m_heightMaps.Clear();
156 if (minZ == maxZ)
157 minZ -= HEIGHT_EQUAL_FUDGE;
158
159 minCoords.Z = minZ;
160 maxCoords.Z = maxZ;
161 Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y);
162
163 // Create the heightmap data structure in the unmanaged space
164 BulletHeightMapInfo mapInfo = new BulletHeightMapInfo(id, heightMap,
165 BulletSimAPI.CreateHeightMapInfo2(id, minCoords, maxCoords, heightMap, TERRAIN_COLLISION_MARGIN));
166 mapInfo.terrainRegionBase = terrainRegionBase;
167 mapInfo.minCoords = minCoords;
168 mapInfo.maxCoords = maxCoords;
169 mapInfo.minZ = minZ;
170 mapInfo.maxZ = maxZ;
171 mapInfo.sizeX = maxCoords.X - minCoords.X;
172 mapInfo.sizeY = maxCoords.Y - minCoords.Y;
173
174 Vector3 centerPos;
175 centerPos.X = minCoords.X + (mapInfo.sizeX / 2f);
176 centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f);
177 centerPos.Z = minZ + (maxZ - minZ) / 2f;
178
179 DetailLog("{0},BSScene.CreateNewTerrainSegment,call,minZ={1},maxZ={2},hMapPtr={3},minC={4},maxC={5}",
180 BSScene.DetailLogZero, minZ, maxZ, mapInfo.Ptr, minCoords, maxCoords);
181 // Create the terrain shape from the mapInfo
182 BulletShape terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
183
184 BulletBody terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2(terrainShape.Ptr,
185 centerPos, Quaternion.Identity));
186
187 BulletSimAPI.SetFriction2(terrainBody.Ptr, m_physicsScene.Params.terrainFriction);
188 BulletSimAPI.SetHitFraction2(terrainBody.Ptr, m_physicsScene.Params.terrainHitFraction);
189 BulletSimAPI.SetRestitution2(terrainBody.Ptr, m_physicsScene.Params.terrainRestitution);
190 BulletSimAPI.SetCollisionFlags2(terrainBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
191 BulletSimAPI.Activate2(terrainBody.Ptr, true);
192
193 // Add the new terrain to the dynamics world
194 BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, terrainBody.Ptr);
195 BulletSimAPI.UpdateSingleAabb2(m_physicsScene.World.Ptr, terrainBody.Ptr);
196
197 // Add the created terrain to the management set. If we are doing mega-regions,
198 // the terrains of our children will be added.
199 m_terrains.Add(terrainRegionBase, terrainBody);
200 m_heightMaps.Add(terrainRegionBase, mapInfo);
201
202 m_terrainModified = true;
203 } 153 }
204 154
155 // The simulator wants to set a new heightmap for the terrain.
205 public void SetTerrain(float[] heightMap) { 156 public void SetTerrain(float[] heightMap) {
206 if (m_worldOffset != Vector3.Zero && m_parentScene != null) 157 if (m_worldOffset != Vector3.Zero && m_parentScene != null)
207 { 158 {
159 // If a child of a mega-region, we shouldn't have any terrain allocated for us
160 ReleaseGroundPlaneAndTerrain();
208 // If doing the mega-prim stuff and we are the child of the zero region, 161 // If doing the mega-prim stuff and we are the child of the zero region,
209 // the terrain is really added to our parent 162 // the terrain is added to our parent
210 if (m_parentScene is BSScene) 163 if (m_parentScene is BSScene)
211 { 164 {
212 ((BSScene)m_parentScene).TerrainManager.SetTerrain(heightMap, m_worldOffset); 165 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
166 BSScene.DetailLogZero, m_worldOffset, m_worldMax);
167 ((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID,
168 heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false);
213 } 169 }
214 } 170 }
215 else 171 else
216 { 172 {
217 // if not doing the mega-prim thing, just change the terrain 173 // If not doing the mega-prim thing, just change the terrain
218 SetTerrain(heightMap, m_worldOffset); 174 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
175
176 UpdateOrCreateTerrain(BSScene.TERRAIN_ID, heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false);
219 } 177 }
220 } 178 }
221 179
222 private void SetTerrain(float[] heightMap, Vector3 tOffset) 180 // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain
181 // based on the passed information. The 'id' should be either the terrain id or
182 // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
183 // The latter feature is for creating child terrains for mega-regions.
184 // If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0)
185 // then a new body and shape is created and the mapInfo is filled.
186 // This call is used for doing the initial terrain creation.
187 // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new
188 // terrain shape is created and added to the body.
189 // This call is most often used to update the heightMap and parameters of the terrain.
190 // The 'doNow' boolean says whether to do all the unmanaged activities right now (like when
191 // calling this routine from initialization or taint-time routines) or whether to delay
192 // all the unmanaged activities to taint-time.
193 private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool doNow)
223 { 194 {
195 DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},doNow={3}",
196 BSScene.DetailLogZero, minCoords, maxCoords, doNow);
197
224 float minZ = float.MaxValue; 198 float minZ = float.MaxValue;
225 float maxZ = float.MinValue; 199 float maxZ = float.MinValue;
226 Vector2 terrainRegionBase = new Vector2(tOffset.X, tOffset.Y); 200 Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y);
227 201
228 int heightMapSize = heightMap.Length; 202 int heightMapSize = heightMap.Length;
229 for (int ii = 0; ii < heightMapSize; ii++) 203 for (int ii = 0; ii < heightMapSize; ii++)
@@ -234,58 +208,162 @@ public class BSTerrainManager
234 } 208 }
235 209
236 // The shape of the terrain is from its base to its extents. 210 // The shape of the terrain is from its base to its extents.
237 Vector3 minCoords, maxCoords;
238 minCoords = tOffset;
239 minCoords.Z = minZ; 211 minCoords.Z = minZ;
240 maxCoords = tOffset;
241 maxCoords.X += Constants.RegionSize;
242 maxCoords.Y += Constants.RegionSize;
243 maxCoords.Z = maxZ; 212 maxCoords.Z = maxZ;
244 213
245 BulletBody terrainBody;
246 BulletHeightMapInfo mapInfo; 214 BulletHeightMapInfo mapInfo;
247 if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo)) 215 if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo))
248 { 216 {
249 terrainBody = m_terrains[terrainRegionBase];
250 // Copy heightMap local and compute some statistics.
251 for (int ii = 0; ii < heightMapSize; ii++)
252 {
253 mapInfo.heightMap[ii] = heightMap[ii];
254 }
255
256 // If this is terrain we know about, it's easy to update 217 // If this is terrain we know about, it's easy to update
257 m_physicsScene.TaintedObject("BSScene.SetTerrain:UpdateExisting", delegate() 218
219 mapInfo.heightMap = heightMap;
220 mapInfo.minCoords = minCoords;
221 mapInfo.maxCoords = maxCoords;
222 mapInfo.minZ = minZ;
223 mapInfo.maxZ = maxZ;
224 mapInfo.sizeX = maxCoords.X - minCoords.X;
225 mapInfo.sizeY = maxCoords.Y - minCoords.Y;
226 DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
227 BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
228
229 BSScene.TaintCallback rebuildOperation = delegate()
258 { 230 {
259 DetailLog("{0},SetTerrain:UpdateExisting,baseX={1},baseY={2},minZ={3},maxZ={4}", 231 if (m_parentScene != null)
260 BSScene.DetailLogZero, tOffset.X, tOffset.Y, minZ, maxZ); 232 {
261 // Fill the existing height map info with the new location and size information 233 // It's possible that Combine() was called after this code was queued.
262 BulletSimAPI.FillHeightMapInfo2(mapInfo.Ptr, mapInfo.ID, minCoords, maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); 234 // If we are a child of combined regions, we don't create any terrain for us.
235 DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero);
263 236
264 // Create a terrain shape based on the new info 237 // Get rid of any terrain that may have been allocated for us.
265 BulletShape terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr)); 238 ReleaseGroundPlaneAndTerrain();
266 239
267 // Swap the shape in the terrain body (this also deletes the old shape) 240 // I hate doing this, but just bail
268 bool success = BulletSimAPI.ReplaceBodyShape2(m_physicsScene.World.Ptr, terrainBody.Ptr, terrainShape.Ptr); 241 return;
242 }
269 243
270 if (!success) 244 if (mapInfo.terrainBody.Ptr != IntPtr.Zero)
271 { 245 {
272 DetailLog("{0},SetTerrain:UpdateExisting,Failed", BSScene.DetailLogZero); 246 // Updating an existing terrain.
273 m_physicsScene.Logger.ErrorFormat("{0} Failed updating terrain heightmap. Region={1}", 247 DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
274 LogHeader, m_physicsScene.RegionName); 248 BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
275 249
250 // Remove from the dynamics world because we're going to mangle this object
251 BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
252
253 // Get rid of the old terrain
254 BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
255 BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr);
256 mapInfo.Ptr = IntPtr.Zero;
257
258 /*
259 // NOTE: This routine is half here because I can't get the terrain shape replacement
260 // to work. In the short term, the above three lines completely delete the old
261 // terrain and the code below recreates one from scratch.
262 // Hopefully the Bullet community will help me out on this one.
263
264 // First, release the old collision shape (there is only one terrain)
265 BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr);
266
267 // Fill the existing height map info with the new location and size information
268 BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID,
269 mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
270
271 // Create a terrain shape based on the new info
272 mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
273
274 // Stuff the shape into the existing terrain body
275 BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr);
276 */
276 } 277 }
277 }); 278 // else
279 {
280 // Creating a new terrain.
281 DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}",
282 BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ);
283
284 mapInfo.ID = id;
285 mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.ID,
286 mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
287
288 // The terrain object initial position is at the center of the object
289 Vector3 centerPos;
290 centerPos.X = minCoords.X + (mapInfo.sizeX / 2f);
291 centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f);
292 centerPos.Z = minZ + ((maxZ - minZ) / 2f);
293
294 // Create the terrain shape from the mapInfo
295 mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
296
297 mapInfo.terrainBody = new BulletBody(mapInfo.ID,
298 BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.Ptr,
299 centerPos, Quaternion.Identity));
300 }
301
302 // Make sure the entry is in the heightmap table
303 m_heightMaps[terrainRegionBase] = mapInfo;
304
305 // Set current terrain attributes
306 BulletSimAPI.SetFriction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainFriction);
307 BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainHitFraction);
308 BulletSimAPI.SetRestitution2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainRestitution);
309 BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
310
311 BulletSimAPI.SetMassProps2(mapInfo.terrainBody.Ptr, 0f, Vector3.Zero);
312 BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.Ptr);
313
314 // Return the new terrain to the world of physical objects
315 BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
316
317 // redo its bounding box now that it is in the world
318 BulletSimAPI.UpdateSingleAabb2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
319
320 // Make sure the new shape is processed.
321 BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true);
322 };
323
324 // There is the option to do the changes now (we're already in 'taint time'), or
325 // to do the Bullet operations later.
326 if (doNow)
327 rebuildOperation();
328 else
329 m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation);
278 } 330 }
279 else 331 else
280 { 332 {
281 // Our mega-prim child is giving us a new terrain to add to the phys world 333 // We don't know about this terrain so either we are creating a new terrain or
282 uint newTerrainID = ++m_terrainCount; 334 // our mega-prim child is giving us a new terrain to add to the phys world
283 335
284 m_physicsScene.TaintedObject("BSScene.SetTerrain:NewTerrain", delegate() 336 // if this is a child terrain, calculate a unique terrain id
337 uint newTerrainID = id;
338 if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
339 newTerrainID = ++m_terrainCount;
340
341 float[] heightMapX = heightMap;
342 Vector3 minCoordsX = minCoords;
343 Vector3 maxCoordsX = maxCoords;
344
345 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}",
346 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
347
348 // Code that must happen at taint-time
349 BSScene.TaintCallback createOperation = delegate()
285 { 350 {
286 DetailLog("{0},SetTerrain:NewTerrain,baseX={1},baseY={2}", BSScene.DetailLogZero, tOffset.X, tOffset.Y); 351 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y);
287 CreateNewTerrainSegment(newTerrainID, heightMap, minCoords, maxCoords); 352 // Create a new mapInfo that will be filled with the new info
288 }); 353 mapInfo = new BulletHeightMapInfo(id, heightMapX,
354 BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, newTerrainID,
355 minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN));
356 // Put the unfilled heightmap info into the collection of same
357 m_heightMaps.Add(terrainRegionBase, mapInfo);
358 // Build the terrain
359 UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true);
360 };
361
362 // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time.
363 if (doNow)
364 createOperation();
365 else
366 m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation);
289 } 367 }
290 } 368 }
291 369
@@ -316,8 +394,8 @@ public class BSTerrainManager
316 lastHeightTY = tY; 394 lastHeightTY = tY;
317 float ret = HEIGHT_GETHEIGHT_RET; 395 float ret = HEIGHT_GETHEIGHT_RET;
318 396
319 int offsetX = ((int)(tX / (int)Constants.RegionSize)) * (int)Constants.RegionSize; 397 int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
320 int offsetY = ((int)(tY / (int)Constants.RegionSize)) * (int)Constants.RegionSize; 398 int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
321 Vector2 terrainBaseXY = new Vector2(offsetX, offsetY); 399 Vector2 terrainBaseXY = new Vector2(offsetX, offsetY);
322 400
323 BulletHeightMapInfo mapInfo; 401 BulletHeightMapInfo mapInfo;
@@ -335,8 +413,8 @@ public class BSTerrainManager
335 } 413 }
336 else 414 else
337 { 415 {
338 m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: x={1}, y={2}", 416 m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
339 LogHeader, tX, tY); 417 LogHeader, m_physicsScene.RegionName, tX, tY);
340 } 418 }
341 lastHeight = ret; 419 lastHeight = ret;
342 return ret; 420 return ret;
@@ -347,20 +425,34 @@ public class BSTerrainManager
347 { 425 {
348 return true; 426 return true;
349 } 427 }
350 // This call says I am a child to region zero in a mega-region. 'pScene' is that 428
351 // of region zero, 'offset' is my offset from regions zero's origin, and 429 // This routine is called two ways:
352 // 'extents' is the largest XY that is handled in my region. 430 // One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum
431 // extent of the combined regions. This is to inform the parent of the size
432 // of the combined regions.
433 // and one with 'offset' as the offset of the child region to the base region,
434 // 'pScene' pointing to the parent and 'extents' of zero. This informs the
435 // child of its relative base and new parent.
353 public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) 436 public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
354 { 437 {
355 m_worldOffset = offset; 438 m_worldOffset = offset;
356 WorldExtents = new Vector2(extents.X, extents.Y); 439 m_worldMax = extents;
357 m_parentScene = pScene; 440 m_parentScene = pScene;
441 if (pScene != null)
442 {
443 // We are a child.
444 // We want m_worldMax to be the highest coordinate of our piece of terrain.
445 m_worldMax = offset + DefaultRegionSize;
446 }
447 DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}",
448 BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax);
358 } 449 }
359 450
360 // Unhook all the combining that I know about. 451 // Unhook all the combining that I know about.
361 public void UnCombine(PhysicsScene pScene) 452 public void UnCombine(PhysicsScene pScene)
362 { 453 {
363 // Just like ODE, for the moment a NOP 454 // Just like ODE, for the moment a NOP
455 DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero);
364 } 456 }
365 457
366 458
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 804d2ea..a0bad3a 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -90,6 +90,8 @@ public class BulletHeightMapInfo
90 public Vector3 maxCoords; 90 public Vector3 maxCoords;
91 public float sizeX, sizeY; 91 public float sizeX, sizeY;
92 public float minZ, maxZ; 92 public float minZ, maxZ;
93 public BulletShape terrainShape;
94 public BulletBody terrainBody;
93} 95}
94 96
95// =============================================================================== 97// ===============================================================================
@@ -462,14 +464,14 @@ public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vecto
462public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot); 464public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot);
463 465
464[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 466[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
465public static extern bool ReplaceBodyShape2(IntPtr sim, IntPtr obj, IntPtr shape); 467public static extern bool SetBodyShape2(IntPtr sim, IntPtr obj, IntPtr shape);
466// ===================================================================================== 468// =====================================================================================
467[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 469[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
468public static extern IntPtr CreateHeightMapInfo2(uint id, Vector3 minCoords, Vector3 maxCoords, 470public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords,
469 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); 471 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
470 472
471[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 473[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
472public static extern IntPtr FillHeightMapInfo2(IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords, 474public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords,
473 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); 475 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
474 476
475[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 477[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]