aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs642
1 files changed, 642 insertions, 0 deletions
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
new file mode 100644
index 0000000..4fcf035
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
@@ -0,0 +1,642 @@
1using System;
2using System.Collections.Generic;
3using System.Reflection;
4using System.IO;
5using System.Diagnostics;
6using System.Threading;
7using log4net;
8using Nini.Config;
9using OpenSim.Framework;
10using OpenSim.Region.Physics.Manager;
11using OpenMetaverse;
12using BulletDotNET;
13
14namespace OpenSim.Region.Physics.BulletDotNETPlugin
15{
16 public class BulletDotNETScene : PhysicsScene
17 {
18 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
19
20 private string m_sceneIdentifier = string.Empty;
21
22 private List<BulletDotNETCharacter> m_characters = new List<BulletDotNETCharacter>();
23 private List<BulletDotNETPrim> m_prims = new List<BulletDotNETPrim>();
24 private List<BulletDotNETPrim> m_activePrims = new List<BulletDotNETPrim>();
25 private List<PhysicsActor> m_taintedActors = new List<PhysicsActor>();
26 private btDiscreteDynamicsWorld m_world;
27 private btAxisSweep3 m_broadphase;
28 private btCollisionConfiguration m_collisionConfiguration;
29 private btConstraintSolver m_solver;
30 private btCollisionDispatcher m_dispatcher;
31 private btHeightfieldTerrainShape m_terrainShape;
32 public btRigidBody TerrainBody;
33 private btVector3 m_terrainPosition;
34 private btVector3 m_gravity;
35 public btMotionState m_terrainMotionState;
36 public btTransform m_terrainTransform;
37 public btVector3 VectorZero;
38 public btQuaternion QuatIdentity;
39 public btTransform TransZero;
40
41 public float geomDefaultDensity = 10.000006836f;
42
43 private float avPIDD = 65f;
44 private float avPIDP = 28f;
45 private float avCapRadius = 0.37f;
46 private float avStandupTensor = 2000000f;
47 private float avDensity = 80f;
48 private float avHeightFudgeFactor = 0.52f;
49 private float avMovementDivisorWalk = 1.0f;
50 private float avMovementDivisorRun = 0.75f;
51
52 private float minimumGroundFlightOffset = 3f;
53
54 public bool meshSculptedPrim = true;
55
56 public float meshSculptLOD = 32;
57 public float MeshSculptphysicalLOD = 16;
58
59 public float bodyPIDD = 35f;
60 public float bodyPIDG = 25;
61 internal int geomCrossingFailuresBeforeOutofbounds = 4;
62
63 public float bodyMotorJointMaxforceTensor = 2;
64
65 public int bodyFramesAutoDisable = 20;
66
67 public float WorldTimeStep = 10f/60f;
68 public const float WorldTimeComp = 1/60f;
69 public float gravityz = -9.8f;
70
71 private float[] _origheightmap; // Used for Fly height. Kitto Flora
72 private bool usingGImpactAlgorithm = false;
73
74 private IConfigSource m_config;
75 private readonly btVector3 worldAabbMin = new btVector3(0, 0, 0);
76 private readonly btVector3 worldAabbMax = new btVector3(Constants.RegionSize, Constants.RegionSize , 9000);
77
78 public IMesher mesher;
79
80 public BulletDotNETScene(string sceneIdentifier)
81 {
82 m_sceneIdentifier = sceneIdentifier;
83 VectorZero = new btVector3(0, 0, 0);
84 QuatIdentity = new btQuaternion(0, 0, 0, 1);
85 TransZero = new btTransform(QuatIdentity, VectorZero);
86 m_gravity = new btVector3(0, 0, gravityz);
87 _origheightmap = new float[(int)Constants.RegionSize * (int)Constants.RegionSize];
88 }
89
90 public override void Initialise(IMesher meshmerizer, IConfigSource config)
91 {
92 mesher = meshmerizer;
93 m_config = config;
94 if (Environment.OSVersion.Platform == PlatformID.Unix)
95 {
96 m_log.Fatal("[BulletDotNET]: This configuration is not supported on *nix currently");
97 Thread.Sleep(5000);
98 Environment.Exit(0);
99 }
100 m_broadphase = new btAxisSweep3(worldAabbMin, worldAabbMax, 16000);
101 m_collisionConfiguration = new btDefaultCollisionConfiguration();
102 m_solver = new btSequentialImpulseConstraintSolver();
103 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
104 m_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);
105 m_world.setGravity(m_gravity);
106 }
107
108 public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size, bool isFlying)
109 {
110 BulletDotNETCharacter chr = new BulletDotNETCharacter(avName, this, position, size, avPIDD, avPIDP,
111 avCapRadius, avStandupTensor, avDensity,
112 avHeightFudgeFactor, avMovementDivisorWalk,
113 avMovementDivisorRun);
114 m_characters.Add(chr);
115 AddPhysicsActorTaint(chr);
116 return chr;
117 }
118
119 public override void RemoveAvatar(PhysicsActor actor)
120 {
121 BulletDotNETCharacter chr = (BulletDotNETCharacter) actor;
122
123 m_characters.Remove(chr);
124 m_world.removeRigidBody(chr.Body);
125 m_world.removeCollisionObject(chr.Body);
126
127 chr.Remove();
128 AddPhysicsActorTaint(chr);
129 //chr = null;
130 }
131
132 public override void RemovePrim(PhysicsActor prim)
133 {
134 if (prim is BulletDotNETPrim)
135 {
136
137 BulletDotNETPrim p = (BulletDotNETPrim)prim;
138
139 p.setPrimForRemoval();
140 AddPhysicsActorTaint(prim);
141 //RemovePrimThreadLocked(p);
142
143 }
144 }
145
146 private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation,
147 IMesh mesh, PrimitiveBaseShape pbs, bool isphysical)
148 {
149 PhysicsVector pos = new PhysicsVector(position.X, position.Y, position.Z);
150 //pos.X = position.X;
151 //pos.Y = position.Y;
152 //pos.Z = position.Z;
153 PhysicsVector siz = new PhysicsVector();
154 siz.X = size.X;
155 siz.Y = size.Y;
156 siz.Z = size.Z;
157 Quaternion rot = rotation;
158
159 BulletDotNETPrim newPrim;
160
161 newPrim = new BulletDotNETPrim(name, this, pos, siz, rot, mesh, pbs, isphysical);
162
163 lock (m_prims)
164 m_prims.Add(newPrim);
165
166
167 return newPrim;
168 }
169
170 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quaternion rotation)
171 {
172 return AddPrimShape(primName, pbs, position, size, rotation, false);
173 }
174
175 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quaternion rotation, bool isPhysical)
176 {
177 PhysicsActor result;
178 IMesh mesh = null;
179
180 //switch (pbs.ProfileShape)
181 //{
182 // case ProfileShape.Square:
183 // //support simple box & hollow box now; later, more shapes
184 // if (needsMeshing(pbs))
185 // {
186 // mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
187 // }
188
189 // break;
190 //}
191
192 if (needsMeshing(pbs))
193 mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
194
195 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
196
197 return result;
198 }
199
200 public override void AddPhysicsActorTaint(PhysicsActor prim)
201 {
202 lock (m_taintedActors)
203 {
204 if (!m_taintedActors.Contains(prim))
205 {
206 m_taintedActors.Add(prim);
207 }
208 }
209 }
210 internal void SetUsingGImpact()
211 {
212 if (!usingGImpactAlgorithm)
213 btGImpactCollisionAlgorithm.registerAlgorithm(m_dispatcher);
214 usingGImpactAlgorithm = true;
215 }
216
217 public override float Simulate(float timeStep)
218 {
219 lock (m_taintedActors)
220 {
221 foreach (PhysicsActor act in m_taintedActors)
222 {
223 if (act is BulletDotNETCharacter)
224 ((BulletDotNETCharacter) act).ProcessTaints(timeStep);
225 if (act is BulletDotNETPrim)
226 ((BulletDotNETPrim)act).ProcessTaints(timeStep);
227 }
228 m_taintedActors.Clear();
229 }
230
231 lock (m_characters)
232 {
233 foreach (BulletDotNETCharacter chr in m_characters)
234 {
235 chr.Move(timeStep);
236 }
237 }
238
239 lock (m_prims)
240 {
241 foreach (BulletDotNETPrim prim in m_prims)
242 {
243 prim.Move(timeStep);
244 }
245 }
246 float steps = m_world.stepSimulation(WorldTimeStep, 5, WorldTimeComp);
247
248 foreach (BulletDotNETCharacter chr in m_characters)
249 {
250 chr.UpdatePositionAndVelocity();
251 }
252
253 foreach (BulletDotNETPrim prm in m_activePrims)
254 {
255 prm.UpdatePositionAndVelocity();
256 }
257
258 return steps;
259 }
260
261 public override void GetResults()
262 {
263
264 }
265
266 public override void SetTerrain(float[] heightMap)
267 {
268 if (m_terrainShape != null)
269 DeleteTerrain();
270
271 float hfmax = -9000;
272 float hfmin = 90000;
273
274 for (int i = 0; i <heightMap.Length;i++)
275 {
276 if (Single.IsNaN(heightMap[i]) || Single.IsInfinity(heightMap[i]))
277 {
278 heightMap[i] = 0f;
279 }
280
281 hfmin = (heightMap[i] < hfmin) ? heightMap[i] : hfmin;
282 hfmax = (heightMap[i] > hfmax) ? heightMap[i] : hfmax;
283 }
284 // store this for later reference.
285 // Note, we're storing it after we check it for anomolies above
286 _origheightmap = heightMap;
287
288 hfmin = 0;
289 hfmax = 256;
290
291 m_terrainShape = new btHeightfieldTerrainShape((int)Constants.RegionSize, (int)Constants.RegionSize, heightMap,
292 1.0f, hfmin, hfmax, (int)btHeightfieldTerrainShape.UPAxis.Z,
293 (int)btHeightfieldTerrainShape.PHY_ScalarType.PHY_FLOAT, false);
294 float AabbCenterX = Constants.RegionSize/2f;
295 float AabbCenterY = Constants.RegionSize/2f;
296
297 float AabbCenterZ = 0;
298 float temphfmin, temphfmax;
299
300 temphfmin = hfmin;
301 temphfmax = hfmax;
302
303 if (temphfmin < 0)
304 {
305 temphfmax = 0 - temphfmin;
306 temphfmin = 0 - temphfmin;
307 }
308 else if (temphfmin > 0)
309 {
310 temphfmax = temphfmax + (0 - temphfmin);
311 //temphfmin = temphfmin + (0 - temphfmin);
312 }
313 AabbCenterZ = temphfmax/2f;
314
315 if (m_terrainPosition == null)
316 {
317 m_terrainPosition = new btVector3(AabbCenterX, AabbCenterY, AabbCenterZ);
318 }
319 else
320 {
321 try
322 {
323 m_terrainPosition.setValue(AabbCenterX, AabbCenterY, AabbCenterZ);
324 }
325 catch (ObjectDisposedException)
326 {
327 m_terrainPosition = new btVector3(AabbCenterX, AabbCenterY, AabbCenterZ);
328 }
329 }
330 if (m_terrainMotionState != null)
331 {
332 m_terrainMotionState.Dispose();
333 m_terrainMotionState = null;
334 }
335 m_terrainTransform = new btTransform(QuatIdentity, m_terrainPosition);
336 m_terrainMotionState = new btDefaultMotionState(m_terrainTransform);
337 TerrainBody = new btRigidBody(0, m_terrainMotionState, m_terrainShape);
338 m_world.addRigidBody(TerrainBody);
339
340
341 }
342
343 public override void SetWaterLevel(float baseheight)
344 {
345
346 }
347
348 public override void DeleteTerrain()
349 {
350 if (TerrainBody != null)
351 {
352 m_world.removeRigidBody(TerrainBody);
353 }
354
355 if (m_terrainShape != null)
356 {
357 m_terrainShape.Dispose();
358 m_terrainShape = null;
359 }
360
361 if (m_terrainMotionState != null)
362 {
363 m_terrainMotionState.Dispose();
364 m_terrainMotionState = null;
365 }
366
367 if (m_terrainTransform != null)
368 {
369 m_terrainTransform.Dispose();
370 m_terrainTransform = null;
371 }
372
373 if (m_terrainPosition != null)
374 {
375 m_terrainPosition.Dispose();
376 m_terrainPosition = null;
377 }
378 }
379
380 public override void Dispose()
381 {
382 disposeAllBodies();
383 m_world.Dispose();
384 m_broadphase.Dispose();
385 ((btDefaultCollisionConfiguration) m_collisionConfiguration).Dispose();
386 ((btSequentialImpulseConstraintSolver) m_solver).Dispose();
387 worldAabbMax.Dispose();
388 worldAabbMin.Dispose();
389 VectorZero.Dispose();
390 QuatIdentity.Dispose();
391 m_gravity.Dispose();
392 VectorZero = null;
393 QuatIdentity = null;
394 }
395
396 public override Dictionary<uint, float> GetTopColliders()
397 {
398 return new Dictionary<uint, float>();
399 }
400
401 public btDiscreteDynamicsWorld getBulletWorld()
402 {
403 return m_world;
404 }
405
406 private void disposeAllBodies()
407 {
408 lock (m_prims)
409 {
410 foreach ( BulletDotNETPrim prim in m_prims)
411 {
412 if (prim.Body != null)
413 m_world.removeRigidBody(prim.Body);
414
415 prim.Dispose();
416 }
417 m_prims.Clear();
418
419 foreach (BulletDotNETCharacter chr in m_characters)
420 {
421 if (chr.Body != null)
422 m_world.removeRigidBody(chr.Body);
423 chr.Dispose();
424 }
425 m_characters.Clear();
426 }
427 }
428
429 public override bool IsThreaded
430 {
431 get { return false; }
432 }
433
434 internal void addCollisionEventReporting(PhysicsActor bulletDotNETCharacter)
435 {
436 //TODO: FIXME:
437 }
438
439 internal void remCollisionEventReporting(PhysicsActor bulletDotNETCharacter)
440 {
441 //TODO: FIXME:
442 }
443
444 internal void AddRigidBody(btRigidBody Body)
445 {
446 m_world.addRigidBody(Body);
447 }
448 [Obsolete("bad!")]
449 internal void removeFromWorld(btRigidBody body)
450 {
451
452 m_world.removeRigidBody(body);
453 }
454
455 internal void removeFromWorld(BulletDotNETPrim prm ,btRigidBody body)
456 {
457 lock (m_prims)
458 {
459 if (m_prims.Contains(prm))
460 {
461 m_world.removeRigidBody(body);
462 }
463 m_prims.Remove(prm);
464 }
465
466 }
467
468 internal float GetWaterLevel()
469 {
470 throw new NotImplementedException();
471 }
472
473 // Recovered for use by fly height. Kitto Flora
474 public float GetTerrainHeightAtXY(float x, float y)
475 {
476 // Teravus: Kitto, this code causes recurring errors that stall physics permenantly unless
477 // the values are checked, so checking below.
478 // Is there any reason that we don't do this in ScenePresence?
479 // The only physics engine that benefits from it in the physics plugin is this one
480
481 if ((int)x > Constants.RegionSize || (int)y > Constants.RegionSize ||
482 (int)x < 0.001f || (int)y < 0.001f)
483 return 0;
484
485 return _origheightmap[(int)y * Constants.RegionSize + (int)x];
486 }
487 // End recovered. Kitto Flora
488
489 /// <summary>
490 /// Routine to figure out if we need to mesh this prim with our mesher
491 /// </summary>
492 /// <param name="pbs"></param>
493 /// <returns></returns>
494 public bool needsMeshing(PrimitiveBaseShape pbs)
495 {
496 // most of this is redundant now as the mesher will return null if it cant mesh a prim
497 // but we still need to check for sculptie meshing being enabled so this is the most
498 // convenient place to do it for now...
499
500 // //if (pbs.PathCurve == (byte)Primitive.PathCurve.Circle && pbs.ProfileCurve == (byte)Primitive.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f)
501 // //m_log.Debug("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + Primitive.UnpackPathScale(pbs.PathScaleY).ToString());
502 int iPropertiesNotSupportedDefault = 0;
503
504 if (pbs.SculptEntry && !meshSculptedPrim)
505 {
506#if SPAM
507 m_log.Warn("NonMesh");
508#endif
509 return false;
510 }
511
512 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
513 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
514 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
515 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
516 {
517
518 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
519 && pbs.ProfileHollow == 0
520 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
521 && pbs.PathBegin == 0 && pbs.PathEnd == 0
522 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
523 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
524 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
525 {
526#if SPAM
527 m_log.Warn("NonMesh");
528#endif
529 return false;
530 }
531 }
532
533 if (pbs.ProfileHollow != 0)
534 iPropertiesNotSupportedDefault++;
535
536 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
537 iPropertiesNotSupportedDefault++;
538
539 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
540 iPropertiesNotSupportedDefault++;
541
542 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
543 iPropertiesNotSupportedDefault++;
544
545 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
546 iPropertiesNotSupportedDefault++;
547
548 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
549 iPropertiesNotSupportedDefault++;
550
551 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
552 iPropertiesNotSupportedDefault++;
553
554 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
555 iPropertiesNotSupportedDefault++;
556
557 // test for torus
558 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
559 {
560 if (pbs.PathCurve == (byte)Extrusion.Curve1)
561 {
562 iPropertiesNotSupportedDefault++;
563 }
564 }
565 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
566 {
567 if (pbs.PathCurve == (byte)Extrusion.Straight)
568 {
569 iPropertiesNotSupportedDefault++;
570 }
571
572 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
573 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
574 {
575 iPropertiesNotSupportedDefault++;
576 }
577 }
578 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
579 {
580 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
581 {
582 iPropertiesNotSupportedDefault++;
583 }
584 }
585 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
586 {
587 if (pbs.PathCurve == (byte)Extrusion.Straight)
588 {
589 iPropertiesNotSupportedDefault++;
590 }
591 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
592 {
593 iPropertiesNotSupportedDefault++;
594 }
595 }
596
597
598 if (iPropertiesNotSupportedDefault == 0)
599 {
600#if SPAM
601 m_log.Warn("NonMesh");
602#endif
603 return false;
604 }
605#if SPAM
606 m_log.Debug("Mesh");
607#endif
608 return true;
609 }
610
611 internal void addActivePrim(BulletDotNETPrim pPrim)
612 {
613 lock (m_activePrims)
614 {
615 if (!m_activePrims.Contains(pPrim))
616 {
617 m_activePrims.Add(pPrim);
618 }
619 }
620 }
621
622 public void remActivePrim(BulletDotNETPrim pDeactivatePrim)
623 {
624 lock (m_activePrims)
625 {
626 m_activePrims.Remove(pDeactivatePrim);
627 }
628 }
629
630 internal void AddPrimToScene(BulletDotNETPrim pPrim)
631 {
632 lock (m_prims)
633 {
634 if (!m_prims.Contains(pPrim))
635 {
636 m_prims.Add(pPrim);
637 m_world.addRigidBody(pPrim.Body);
638 }
639 }
640 }
641 }
642}