diff options
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin/OdePlugin.cs')
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | 220 |
1 files changed, 188 insertions, 32 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs index 17dbd0a..366f30b 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | |||
@@ -86,6 +86,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
86 | private IntPtr contactgroup; | 86 | private IntPtr contactgroup; |
87 | private IntPtr LandGeom = (IntPtr) 0; | 87 | private IntPtr LandGeom = (IntPtr) 0; |
88 | private double[] _heightmap; | 88 | private double[] _heightmap; |
89 | private float[] _origheightmap; | ||
89 | private d.NearCallback nearCallback; | 90 | private d.NearCallback nearCallback; |
90 | public d.TriCallback triCallback; | 91 | public d.TriCallback triCallback; |
91 | public d.TriArrayCallback triArrayCallback; | 92 | public d.TriArrayCallback triArrayCallback; |
@@ -115,6 +116,12 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
115 | 116 | ||
116 | public IMesher mesher; | 117 | public IMesher mesher; |
117 | 118 | ||
119 | |||
120 | /// <summary> | ||
121 | /// Initiailizes the scene | ||
122 | /// Sets many properties that ODE requires to be stable | ||
123 | /// These settings need to be tweaked 'exactly' right or weird stuff happens. | ||
124 | /// </summary> | ||
118 | public OdeScene() | 125 | public OdeScene() |
119 | { | 126 | { |
120 | nearCallback = near; | 127 | nearCallback = near; |
@@ -128,17 +135,27 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
128 | contact.surface.soft_cfm = 0.00003f; | 135 | contact.surface.soft_cfm = 0.00003f; |
129 | */ | 136 | */ |
130 | 137 | ||
138 | // Centeral contact friction and bounce | ||
131 | contact.surface.mu = 250.0f; | 139 | contact.surface.mu = 250.0f; |
132 | contact.surface.bounce = 0.2f; | 140 | contact.surface.bounce = 0.2f; |
133 | 141 | ||
142 | // Terrain contact friction and Bounce | ||
143 | // This is the *non* moving version. Use this when an avatar | ||
144 | // isn't moving to keep it in place better | ||
134 | TerrainContact.surface.mode |= d.ContactFlags.SoftERP; | 145 | TerrainContact.surface.mode |= d.ContactFlags.SoftERP; |
135 | TerrainContact.surface.mu = 550.0f; | 146 | TerrainContact.surface.mu = 550.0f; |
136 | TerrainContact.surface.bounce = 0.1f; | 147 | TerrainContact.surface.bounce = 0.1f; |
137 | TerrainContact.surface.soft_erp = 0.1025f; | 148 | TerrainContact.surface.soft_erp = 0.1025f; |
138 | 149 | ||
150 | // Prim contact friction and bounce | ||
151 | // THis is the *non* moving version of friction and bounce | ||
152 | // Use this when an avatar comes in contact with a prim | ||
153 | // and is moving | ||
139 | AvatarMovementprimContact.surface.mu = 150.0f; | 154 | AvatarMovementprimContact.surface.mu = 150.0f; |
140 | AvatarMovementprimContact.surface.bounce = 0.1f; | 155 | AvatarMovementprimContact.surface.bounce = 0.1f; |
141 | 156 | ||
157 | // Terrain contact friction bounce and various error correcting calculations | ||
158 | // Use this when an avatar is in contact with the terrain and moving. | ||
142 | AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP; | 159 | AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP; |
143 | AvatarMovementTerrainContact.surface.mu = 150.0f; | 160 | AvatarMovementTerrainContact.surface.mu = 150.0f; |
144 | AvatarMovementTerrainContact.surface.bounce = 0.1f; | 161 | AvatarMovementTerrainContact.surface.bounce = 0.1f; |
@@ -146,6 +163,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
146 | 163 | ||
147 | lock (OdeLock) | 164 | lock (OdeLock) |
148 | { | 165 | { |
166 | // Creat the world and the first space | ||
149 | world = d.WorldCreate(); | 167 | world = d.WorldCreate(); |
150 | space = d.HashSpaceCreate(IntPtr.Zero); | 168 | space = d.HashSpaceCreate(IntPtr.Zero); |
151 | d.HashSpaceSetLevels(space, -4, 128); | 169 | d.HashSpaceSetLevels(space, -4, 128); |
@@ -153,15 +171,25 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
153 | //contactgroup | 171 | //contactgroup |
154 | 172 | ||
155 | 173 | ||
174 | // Set the gravity,, don't disable things automatically (we set it explicitly on some things) | ||
175 | |||
156 | d.WorldSetGravity(world, 0.0f, 0.0f, -10.0f); | 176 | d.WorldSetGravity(world, 0.0f, 0.0f, -10.0f); |
157 | d.WorldSetAutoDisableFlag(world, false); | 177 | d.WorldSetAutoDisableFlag(world, false); |
158 | d.WorldSetContactSurfaceLayer(world, 0.001f); | 178 | d.WorldSetContactSurfaceLayer(world, 0.001f); |
179 | |||
180 | // Set how many steps we go without running collision testing | ||
181 | // This is in addition to the step size. | ||
182 | // Essentially Steps * m_physicsiterations | ||
159 | d.WorldSetQuickStepNumIterations(world, m_physicsiterations); | 183 | d.WorldSetQuickStepNumIterations(world, m_physicsiterations); |
160 | d.WorldSetContactMaxCorrectingVel(world, 1000.0f); | 184 | ///d.WorldSetContactMaxCorrectingVel(world, 1000.0f); |
161 | } | 185 | } |
162 | 186 | ||
187 | // zero out a heightmap array float array (single dimention [flattened])) | ||
163 | _heightmap = new double[514*514]; | 188 | _heightmap = new double[514*514]; |
164 | 189 | ||
190 | |||
191 | // Zero out the prim spaces array (we split our space into smaller spaces so | ||
192 | // we can hit test less. | ||
165 | for (int i = 0; i < staticPrimspace.GetLength(0); i++) | 193 | for (int i = 0; i < staticPrimspace.GetLength(0); i++) |
166 | { | 194 | { |
167 | for (int j = 0; j < staticPrimspace.GetLength(1); j++) | 195 | for (int j = 0; j < staticPrimspace.GetLength(1); j++) |
@@ -171,19 +199,35 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
171 | } | 199 | } |
172 | } | 200 | } |
173 | 201 | ||
202 | // Initialize the mesh plugin | ||
174 | public override void Initialise(IMesher meshmerizer) | 203 | public override void Initialise(IMesher meshmerizer) |
175 | { | 204 | { |
176 | mesher = meshmerizer; | 205 | mesher = meshmerizer; |
177 | } | 206 | } |
178 | 207 | ||
208 | /// <summary> | ||
209 | /// Debug space message for printing the space that a prim/avatar is in. | ||
210 | /// </summary> | ||
211 | /// <param name="pos"></param> | ||
212 | /// <returns>Returns which split up space the given position is in.</returns> | ||
179 | public string whichspaceamIin(PhysicsVector pos) | 213 | public string whichspaceamIin(PhysicsVector pos) |
180 | { | 214 | { |
181 | return calculateSpaceForGeom(pos).ToString(); | 215 | return calculateSpaceForGeom(pos).ToString(); |
182 | } | 216 | } |
183 | 217 | ||
218 | /// <summary> | ||
219 | /// This is our near callback. A geometry is near a body | ||
220 | /// </summary> | ||
221 | /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param> | ||
222 | /// <param name="g1">a geometry or space</param> | ||
223 | /// <param name="g2">another geometry or space</param> | ||
184 | private void near(IntPtr space, IntPtr g1, IntPtr g2) | 224 | private void near(IntPtr space, IntPtr g1, IntPtr g2) |
185 | { | 225 | { |
186 | // no lock here! It's invoked from within Simulate(), which is thread-locked | 226 | // no lock here! It's invoked from within Simulate(), which is thread-locked |
227 | |||
228 | // Test if we're collidng a geom with a space. | ||
229 | // If so we have to drill down into the space recursively | ||
230 | |||
187 | if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2)) | 231 | if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2)) |
188 | { | 232 | { |
189 | // Separating static prim geometry spaces. | 233 | // Separating static prim geometry spaces. |
@@ -192,7 +236,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
192 | // contact points in the space | 236 | // contact points in the space |
193 | 237 | ||
194 | d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); | 238 | d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); |
195 | //Colliding a space or a geom with a space or a geom. | 239 | //Colliding a space or a geom with a space or a geom. so drill down |
196 | 240 | ||
197 | //Collide all geoms in each space.. | 241 | //Collide all geoms in each space.. |
198 | //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback); | 242 | //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback); |
@@ -226,12 +270,13 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
226 | name2 = "null"; | 270 | name2 = "null"; |
227 | } | 271 | } |
228 | 272 | ||
229 | if (id == d.GeomClassID.TriMeshClass) | 273 | //if (id == d.GeomClassID.TriMeshClass) |
230 | { | 274 | //{ |
231 | // MainLog.Instance.Verbose("near: A collision was detected between {1} and {2}", 0, name1, name2); | 275 | // MainLog.Instance.Verbose("near: A collision was detected between {1} and {2}", 0, name1, name2); |
232 | //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); | 276 | //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); |
233 | } | 277 | //} |
234 | 278 | ||
279 | // Figure out how many contact points we have | ||
235 | int count = 0; | 280 | int count = 0; |
236 | try | 281 | try |
237 | { | 282 | { |
@@ -244,13 +289,15 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
244 | base.TriggerPhysicsBasedRestart(); | 289 | base.TriggerPhysicsBasedRestart(); |
245 | } | 290 | } |
246 | 291 | ||
292 | PhysicsActor p1; | ||
293 | PhysicsActor p2; | ||
294 | |||
247 | for (int i = 0; i < count; i++) | 295 | for (int i = 0; i < count; i++) |
248 | { | 296 | { |
249 | IntPtr joint; | 297 | IntPtr joint; |
250 | // If we're colliding with terrain, use 'TerrainContact' instead of contact. | 298 | // If we're colliding with terrain, use 'TerrainContact' instead of contact. |
251 | // allows us to have different settings | 299 | // allows us to have different settings |
252 | PhysicsActor p1; | 300 | |
253 | PhysicsActor p2; | ||
254 | 301 | ||
255 | if (!actor_name_map.TryGetValue(g1, out p1)) | 302 | if (!actor_name_map.TryGetValue(g1, out p1)) |
256 | { | 303 | { |
@@ -267,14 +314,14 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
267 | 314 | ||
268 | switch (p1.PhysicsActorType) | 315 | switch (p1.PhysicsActorType) |
269 | { | 316 | { |
270 | case (int) ActorTypes.Agent: | 317 | case (int)ActorTypes.Agent: |
271 | p2.CollidingObj = true; | 318 | p2.CollidingObj = true; |
272 | break; | 319 | break; |
273 | case (int) ActorTypes.Prim: | 320 | case (int)ActorTypes.Prim: |
274 | if (p2.Velocity.X > 0 || p2.Velocity.Y > 0 || p2.Velocity.Z > 0) | 321 | if (p2.Velocity.X > 0 || p2.Velocity.Y > 0 || p2.Velocity.Z > 0) |
275 | p2.CollidingObj = true; | 322 | p2.CollidingObj = true; |
276 | break; | 323 | break; |
277 | case (int) ActorTypes.Unknown: | 324 | case (int)ActorTypes.Unknown: |
278 | p2.CollidingGround = true; | 325 | p2.CollidingGround = true; |
279 | break; | 326 | break; |
280 | default: | 327 | default: |
@@ -288,11 +335,15 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
288 | 335 | ||
289 | if (contacts[i].depth >= 0.08f) | 336 | if (contacts[i].depth >= 0.08f) |
290 | { | 337 | { |
338 | /* This is disabled at the moment only because it needs more tweaking | ||
339 | It will eventually be uncommented | ||
340 | |||
291 | if (contacts[i].depth >= 1.00f) | 341 | if (contacts[i].depth >= 1.00f) |
292 | { | 342 | { |
293 | //MainLog.Instance.Debug("PHYSICS",contacts[i].depth.ToString()); | 343 | //MainLog.Instance.Debug("PHYSICS",contacts[i].depth.ToString()); |
294 | } | 344 | } |
295 | // If you interpenetrate a prim with an agent | 345 | |
346 | //If you interpenetrate a prim with an agent | ||
296 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent && | 347 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent && |
297 | p1.PhysicsActorType == (int) ActorTypes.Prim) || | 348 | p1.PhysicsActorType == (int) ActorTypes.Prim) || |
298 | (p1.PhysicsActorType == (int) ActorTypes.Agent && | 349 | (p1.PhysicsActorType == (int) ActorTypes.Agent && |
@@ -300,35 +351,37 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
300 | { | 351 | { |
301 | if (p2.PhysicsActorType == (int) ActorTypes.Agent) | 352 | if (p2.PhysicsActorType == (int) ActorTypes.Agent) |
302 | { | 353 | { |
303 | //p2.CollidingObj = true; | 354 | p2.CollidingObj = true; |
304 | //contacts[i].depth = 0.003f; | 355 | contacts[i].depth = 0.003f; |
305 | //p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f); | 356 | p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f); |
306 | //OdeCharacter character = (OdeCharacter) p2; | 357 | OdeCharacter character = (OdeCharacter) p2; |
307 | //character.SetPidStatus(true); | 358 | character.SetPidStatus(true); |
308 | //contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p1.Size.X / 2), contacts[i].pos.Y + (p1.Size.Y / 2), contacts[i].pos.Z + (p1.Size.Z / 2)); | 359 | contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p1.Size.X / 2), contacts[i].pos.Y + (p1.Size.Y / 2), contacts[i].pos.Z + (p1.Size.Z / 2)); |
309 | 360 | ||
310 | } | 361 | } |
311 | else | 362 | else |
312 | { | 363 | { |
313 | 364 | ||
314 | //contacts[i].depth = 0.0000000f; | 365 | contacts[i].depth = 0.0000000f; |
315 | } | 366 | } |
316 | if (p1.PhysicsActorType == (int) ActorTypes.Agent) | 367 | if (p1.PhysicsActorType == (int) ActorTypes.Agent) |
317 | { | 368 | { |
318 | 369 | ||
319 | //p1.CollidingObj = true; | 370 | p1.CollidingObj = true; |
320 | //contacts[i].depth = 0.003f; | 371 | contacts[i].depth = 0.003f; |
321 | //p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f); | 372 | p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f); |
322 | //contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p2.Size.X / 2), contacts[i].pos.Y + (p2.Size.Y / 2), contacts[i].pos.Z + (p2.Size.Z / 2)); | 373 | contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p2.Size.X / 2), contacts[i].pos.Y + (p2.Size.Y / 2), contacts[i].pos.Z + (p2.Size.Z / 2)); |
323 | //OdeCharacter character = (OdeCharacter)p1; | 374 | OdeCharacter character = (OdeCharacter)p1; |
324 | //character.SetPidStatus(true); | 375 | character.SetPidStatus(true); |
325 | } | 376 | } |
326 | else | 377 | else |
327 | { | 378 | { |
328 | 379 | ||
329 | //contacts[i].depth = 0.0000000f; | 380 | contacts[i].depth = 0.0000000f; |
330 | } | 381 | } |
331 | } | 382 | } |
383 | */ | ||
384 | |||
332 | // If you interpenetrate a prim with another prim | 385 | // If you interpenetrate a prim with another prim |
333 | if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim) | 386 | if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim) |
334 | { | 387 | { |
@@ -337,6 +390,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
337 | } | 390 | } |
338 | if (contacts[i].depth >= 1.00f) | 391 | if (contacts[i].depth >= 1.00f) |
339 | { | 392 | { |
393 | OpenSim.Framework.Console.MainLog.Instance.Verbose("P", contacts[i].depth.ToString()); | ||
340 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent && | 394 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent && |
341 | p1.PhysicsActorType == (int) ActorTypes.Unknown) || | 395 | p1.PhysicsActorType == (int) ActorTypes.Unknown) || |
342 | (p1.PhysicsActorType == (int) ActorTypes.Agent && | 396 | (p1.PhysicsActorType == (int) ActorTypes.Agent && |
@@ -347,7 +401,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
347 | OdeCharacter character = (OdeCharacter) p2; | 401 | OdeCharacter character = (OdeCharacter) p2; |
348 | 402 | ||
349 | //p2.CollidingObj = true; | 403 | //p2.CollidingObj = true; |
350 | contacts[i].depth = 0.003f; | 404 | contacts[i].depth = 0.00000003f; |
351 | p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 0.5f); | 405 | p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 0.5f); |
352 | contacts[i].pos = | 406 | contacts[i].pos = |
353 | new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), | 407 | new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), |
@@ -363,7 +417,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
363 | OdeCharacter character = (OdeCharacter)p1; | 417 | OdeCharacter character = (OdeCharacter)p1; |
364 | 418 | ||
365 | //p2.CollidingObj = true; | 419 | //p2.CollidingObj = true; |
366 | contacts[i].depth = 0.003f; | 420 | contacts[i].depth = 0.00000003f; |
367 | p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 0.5f); | 421 | p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 0.5f); |
368 | contacts[i].pos = | 422 | contacts[i].pos = |
369 | new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), | 423 | new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), |
@@ -383,30 +437,39 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
383 | 437 | ||
384 | if (contacts[i].depth >= 0f) | 438 | if (contacts[i].depth >= 0f) |
385 | { | 439 | { |
440 | // If we're collidng against terrain | ||
386 | if (name1 == "Terrain" || name2 == "Terrain") | 441 | if (name1 == "Terrain" || name2 == "Terrain") |
387 | { | 442 | { |
443 | // If we're moving | ||
388 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && | 444 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && |
389 | (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) | 445 | (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) |
390 | { | 446 | { |
447 | // Use the movement terrain contact | ||
391 | AvatarMovementTerrainContact.geom = contacts[i]; | 448 | AvatarMovementTerrainContact.geom = contacts[i]; |
392 | joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact); | 449 | joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact); |
393 | } | 450 | } |
394 | else | 451 | else |
395 | { | 452 | { |
453 | // Use the non moving terrain contact | ||
396 | TerrainContact.geom = contacts[i]; | 454 | TerrainContact.geom = contacts[i]; |
397 | joint = d.JointCreateContact(world, contactgroup, ref TerrainContact); | 455 | joint = d.JointCreateContact(world, contactgroup, ref TerrainContact); |
398 | } | 456 | } |
399 | } | 457 | } |
400 | else | 458 | else |
401 | { | 459 | { |
460 | // we're colliding with prim or avatar | ||
461 | |||
462 | // check if we're moving | ||
402 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && | 463 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && |
403 | (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) | 464 | (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) |
404 | { | 465 | { |
466 | // Use the Movement prim contact | ||
405 | AvatarMovementprimContact.geom = contacts[i]; | 467 | AvatarMovementprimContact.geom = contacts[i]; |
406 | joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); | 468 | joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); |
407 | } | 469 | } |
408 | else | 470 | else |
409 | { | 471 | { |
472 | // Use the non movement contact | ||
410 | contact.geom = contacts[i]; | 473 | contact.geom = contacts[i]; |
411 | joint = d.JointCreateContact(world, contactgroup, ref contact); | 474 | joint = d.JointCreateContact(world, contactgroup, ref contact); |
412 | } | 475 | } |
@@ -416,6 +479,11 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
416 | 479 | ||
417 | if (count > 3) | 480 | if (count > 3) |
418 | { | 481 | { |
482 | // If there are more then 3 contact points, it's likely | ||
483 | // that we've got a pile of objects | ||
484 | // | ||
485 | // We don't want to send out hundreds of terse updates over and over again | ||
486 | // so lets throttle them and send them again after it's somewhat sorted out. | ||
419 | p2.ThrottleUpdates = true; | 487 | p2.ThrottleUpdates = true; |
420 | } | 488 | } |
421 | //System.Console.WriteLine(count.ToString()); | 489 | //System.Console.WriteLine(count.ToString()); |
@@ -423,16 +491,43 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
423 | } | 491 | } |
424 | } | 492 | } |
425 | } | 493 | } |
494 | private float GetTerrainHeightAtXY(float x, float y) | ||
495 | { | ||
496 | return (float)_origheightmap[(int) y*256 + (int) x]; | ||
497 | |||
426 | 498 | ||
499 | } | ||
500 | |||
501 | /// <summary> | ||
502 | /// This is our collision testing routine in ODE | ||
503 | /// </summary> | ||
504 | /// <param name="timeStep"></param> | ||
427 | private void collision_optimized(float timeStep) | 505 | private void collision_optimized(float timeStep) |
428 | { | 506 | { |
429 | foreach (OdeCharacter chr in _characters) | 507 | foreach (OdeCharacter chr in _characters) |
430 | { | 508 | { |
509 | // Reset the collision values to false | ||
510 | // since we don't know if we're colliding yet | ||
511 | |||
431 | chr.IsColliding = false; | 512 | chr.IsColliding = false; |
432 | chr.CollidingGround = false; | 513 | chr.CollidingGround = false; |
433 | chr.CollidingObj = false; | 514 | chr.CollidingObj = false; |
515 | |||
516 | // test the avatar's geometry for collision with the space | ||
517 | // This will return near and the space that they are the closest to | ||
518 | // And we'll run this again against the avatar and the space segment | ||
519 | // This will return with a bunch of possible objects in the space segment | ||
520 | // and we'll run it again on all of them. | ||
521 | |||
434 | d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); | 522 | d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); |
523 | //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y); | ||
524 | //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10) | ||
525 | //{ | ||
526 | //chr.Position.Z = terrainheight + 10.0f; | ||
527 | //forcedZ = true; | ||
528 | //} | ||
435 | } | 529 | } |
530 | |||
436 | // If the sim is running slow this frame, | 531 | // If the sim is running slow this frame, |
437 | // don't process collision for prim! | 532 | // don't process collision for prim! |
438 | if (timeStep < (m_SkipFramesAtms/3)) | 533 | if (timeStep < (m_SkipFramesAtms/3)) |
@@ -469,6 +564,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
469 | // This if may not need to be there.. it might be skipped anyway. | 564 | // This if may not need to be there.. it might be skipped anyway. |
470 | if (d.BodyIsEnabled(chr.Body)) | 565 | if (d.BodyIsEnabled(chr.Body)) |
471 | { | 566 | { |
567 | // Collide test the prims with the terrain.. since if you don't do this, | ||
568 | // next frame, all of the physical prim in the scene will awaken and explode upwards | ||
472 | d.SpaceCollide2(LandGeom, chr.prim_geom, IntPtr.Zero, nearCallback); | 569 | d.SpaceCollide2(LandGeom, chr.prim_geom, IntPtr.Zero, nearCallback); |
473 | } | 570 | } |
474 | } | 571 | } |
@@ -509,6 +606,15 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
509 | } | 606 | } |
510 | } | 607 | } |
511 | 608 | ||
609 | /// <summary> | ||
610 | /// This is called from within simulate but outside the locked portion | ||
611 | /// We need to do our own locking here | ||
612 | /// Essentially, we need to remove the prim from our space segment, whatever segment it's in. | ||
613 | /// | ||
614 | /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory | ||
615 | /// that the space was using. | ||
616 | /// </summary> | ||
617 | /// <param name="prim"></param> | ||
512 | public void RemovePrimThreadLocked(OdePrim prim) | 618 | public void RemovePrimThreadLocked(OdePrim prim) |
513 | { | 619 | { |
514 | lock (OdeLock) | 620 | lock (OdeLock) |
@@ -567,7 +673,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
567 | _prims.Remove(prim); | 673 | _prims.Remove(prim); |
568 | } | 674 | } |
569 | } | 675 | } |
570 | 676 | /// <summary> | |
677 | /// Takes a space pointer and zeros out the array we're using to hold the spaces | ||
678 | /// </summary> | ||
679 | /// <param name="space"></param> | ||
571 | public void resetSpaceArrayItemToZero(IntPtr space) | 680 | public void resetSpaceArrayItemToZero(IntPtr space) |
572 | { | 681 | { |
573 | for (int x = 0; x < staticPrimspace.GetLength(0); x++) | 682 | for (int x = 0; x < staticPrimspace.GetLength(0); x++) |
@@ -585,15 +694,25 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
585 | staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero; | 694 | staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero; |
586 | } | 695 | } |
587 | 696 | ||
697 | /// <summary> | ||
698 | /// Called when a static prim moves. Allocates a space for the prim based on it's position | ||
699 | /// </summary> | ||
700 | /// <param name="geom">the pointer to the geom that moved</param> | ||
701 | /// <param name="pos">the position that the geom moved to</param> | ||
702 | /// <param name="currentspace">a pointer to the space it was in before it was moved.</param> | ||
703 | /// <returns>a pointer to the new space it's in</returns> | ||
588 | public IntPtr recalculateSpaceForGeom(IntPtr geom, PhysicsVector pos, IntPtr currentspace) | 704 | public IntPtr recalculateSpaceForGeom(IntPtr geom, PhysicsVector pos, IntPtr currentspace) |
589 | { | 705 | { |
590 | //Todo recalculate space the prim is in. | 706 | |
591 | // Called from setting the Position and Size of an ODEPrim so | 707 | // Called from setting the Position and Size of an ODEPrim so |
592 | // it's already in locked space. | 708 | // it's already in locked space. |
593 | 709 | ||
594 | // we don't want to remove the main space | 710 | // we don't want to remove the main space |
595 | // we don't need to test physical here because this function should | 711 | // we don't need to test physical here because this function should |
596 | // never be called if the prim is physical(active) | 712 | // never be called if the prim is physical(active) |
713 | |||
714 | // All physical prim end up in the root space | ||
715 | |||
597 | if (currentspace != space) | 716 | if (currentspace != space) |
598 | { | 717 | { |
599 | if (d.SpaceQuery(currentspace, geom) && currentspace != (IntPtr) 0) | 718 | if (d.SpaceQuery(currentspace, geom) && currentspace != (IntPtr) 0) |
@@ -707,6 +826,12 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
707 | return newspace; | 826 | return newspace; |
708 | } | 827 | } |
709 | 828 | ||
829 | /// <summary> | ||
830 | /// Creates a new space at X Y | ||
831 | /// </summary> | ||
832 | /// <param name="iprimspaceArrItemX"></param> | ||
833 | /// <param name="iprimspaceArrItemY"></param> | ||
834 | /// <returns>A pointer to the created space</returns> | ||
710 | public IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY) | 835 | public IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY) |
711 | { | 836 | { |
712 | // creating a new space for prim and inserting it into main space. | 837 | // creating a new space for prim and inserting it into main space. |
@@ -715,6 +840,11 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
715 | return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]; | 840 | return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]; |
716 | } | 841 | } |
717 | 842 | ||
843 | /// <summary> | ||
844 | /// Calculates the space the prim should be in by it's position | ||
845 | /// </summary> | ||
846 | /// <param name="pos"></param> | ||
847 | /// <returns>a pointer to the space. This could be a new space or reused space.</returns> | ||
718 | public IntPtr calculateSpaceForGeom(PhysicsVector pos) | 848 | public IntPtr calculateSpaceForGeom(PhysicsVector pos) |
719 | { | 849 | { |
720 | int[] xyspace = calculateSpaceArrayItemFromPos(pos); | 850 | int[] xyspace = calculateSpaceArrayItemFromPos(pos); |
@@ -725,6 +855,11 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
725 | return locationbasedspace; | 855 | return locationbasedspace; |
726 | } | 856 | } |
727 | 857 | ||
858 | /// <summary> | ||
859 | /// Holds the space allocation logic | ||
860 | /// </summary> | ||
861 | /// <param name="pos"></param> | ||
862 | /// <returns>an array item based on the position</returns> | ||
728 | public int[] calculateSpaceArrayItemFromPos(PhysicsVector pos) | 863 | public int[] calculateSpaceArrayItemFromPos(PhysicsVector pos) |
729 | { | 864 | { |
730 | int[] returnint = new int[2]; | 865 | int[] returnint = new int[2]; |
@@ -837,7 +972,11 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
837 | return 1; | 972 | return 1; |
838 | } | 973 | } |
839 | 974 | ||
840 | 975 | /// <summary> | |
976 | /// Routine to figure out if we need to mesh this prim with our mesher | ||
977 | /// </summary> | ||
978 | /// <param name="pbs"></param> | ||
979 | /// <returns></returns> | ||
841 | public bool needsMeshing(PrimitiveBaseShape pbs) | 980 | public bool needsMeshing(PrimitiveBaseShape pbs) |
842 | { | 981 | { |
843 | if (pbs.ProfileHollow != 0) | 982 | if (pbs.ProfileHollow != 0) |
@@ -879,6 +1018,12 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
879 | return result; | 1018 | return result; |
880 | } | 1019 | } |
881 | 1020 | ||
1021 | /// <summary> | ||
1022 | /// Called after our prim properties are set Scale, position etc. | ||
1023 | /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex | ||
1024 | /// This assures us that we have no race conditions | ||
1025 | /// </summary> | ||
1026 | /// <param name="prim"></param> | ||
882 | public override void AddPhysicsActorTaint(PhysicsActor prim) | 1027 | public override void AddPhysicsActorTaint(PhysicsActor prim) |
883 | { | 1028 | { |
884 | if (prim is OdePrim) | 1029 | if (prim is OdePrim) |
@@ -889,6 +1034,15 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
889 | } | 1034 | } |
890 | } | 1035 | } |
891 | 1036 | ||
1037 | /// <summary> | ||
1038 | /// This is our main simulate loop | ||
1039 | /// It's thread locked by a Mutex in the scene. | ||
1040 | /// It holds Collisions, it instructs ODE to step through the physical reactions | ||
1041 | /// It moves the objects around in memory | ||
1042 | /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup) | ||
1043 | /// </summary> | ||
1044 | /// <param name="timeStep"></param> | ||
1045 | /// <returns></returns> | ||
892 | public override float Simulate(float timeStep) | 1046 | public override float Simulate(float timeStep) |
893 | { | 1047 | { |
894 | float fps = 0; | 1048 | float fps = 0; |
@@ -904,7 +1058,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
904 | 1058 | ||
905 | if (step_time >= m_SkipFramesAtms) | 1059 | if (step_time >= m_SkipFramesAtms) |
906 | { | 1060 | { |
907 | // Instead of trying to catch up, it'll do one physics frame only | 1061 | // Instead of trying to catch up, it'll do 5 physics frames only |
908 | step_time = ODE_STEPSIZE; | 1062 | step_time = ODE_STEPSIZE; |
909 | m_physicsiterations = 5; | 1063 | m_physicsiterations = 5; |
910 | } | 1064 | } |
@@ -960,6 +1114,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
960 | { | 1114 | { |
961 | actor.UpdatePositionAndVelocity(); | 1115 | actor.UpdatePositionAndVelocity(); |
962 | } | 1116 | } |
1117 | |||
963 | bool processedtaints = false; | 1118 | bool processedtaints = false; |
964 | foreach (OdePrim prim in _taintedPrim) | 1119 | foreach (OdePrim prim in _taintedPrim) |
965 | { | 1120 | { |
@@ -970,6 +1125,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
970 | } | 1125 | } |
971 | processedtaints = true; | 1126 | processedtaints = true; |
972 | } | 1127 | } |
1128 | |||
973 | if (processedtaints) | 1129 | if (processedtaints) |
974 | _taintedPrim = new List<OdePrim>(); | 1130 | _taintedPrim = new List<OdePrim>(); |
975 | 1131 | ||
@@ -1152,7 +1308,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1152 | // this._heightmap[i] = (double)heightMap[i]; | 1308 | // this._heightmap[i] = (double)heightMap[i]; |
1153 | // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) | 1309 | // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) |
1154 | // also, creating a buffer zone of one extra sample all around | 1310 | // also, creating a buffer zone of one extra sample all around |
1155 | 1311 | _origheightmap = heightMap; | |
1156 | const uint heightmapWidth = m_regionWidth + 2; | 1312 | const uint heightmapWidth = m_regionWidth + 2; |
1157 | const uint heightmapHeight = m_regionHeight + 2; | 1313 | const uint heightmapHeight = m_regionHeight + 2; |
1158 | const uint heightmapWidthSamples = 2*m_regionWidth + 2; | 1314 | const uint heightmapWidthSamples = 2*m_regionWidth + 2; |