diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSScene.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 230 |
1 files changed, 53 insertions, 177 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 4a468af..52997dd 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -56,7 +56,6 @@ using OpenMetaverse; | |||
56 | // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect | 56 | // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect |
57 | // Implement LockAngularMotion | 57 | // Implement LockAngularMotion |
58 | // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) | 58 | // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) |
59 | // Does NeedsMeshing() really need to exclude all the different shapes? | ||
60 | // Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. | 59 | // Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. |
61 | // Add PID movement operations. What does ScenePresence.MoveToTarget do? | 60 | // Add PID movement operations. What does ScenePresence.MoveToTarget do? |
62 | // Check terrain size. 128 or 127? | 61 | // Check terrain size. 128 or 127? |
@@ -79,7 +78,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
79 | private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>(); | 78 | private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>(); |
80 | // Following is a kludge and can be removed when avatar animation updating is | 79 | // Following is a kludge and can be removed when avatar animation updating is |
81 | // moved to a better place. | 80 | // moved to a better place. |
82 | private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>(); | 81 | private HashSet<BSPhysObject> m_avatarsWithCollisions = new HashSet<BSPhysObject>(); |
83 | 82 | ||
84 | // List of all the objects that have vehicle properties and should be called | 83 | // List of all the objects that have vehicle properties and should be called |
85 | // to update each physics step. | 84 | // to update each physics step. |
@@ -111,11 +110,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
111 | private long m_simulationStep = 0; | 110 | private long m_simulationStep = 0; |
112 | public long SimulationStep { get { return m_simulationStep; } } | 111 | public long SimulationStep { get { return m_simulationStep; } } |
113 | 112 | ||
114 | // The length of the last timestep we were asked to simulate. | ||
115 | // This is used by the vehicle code. Since the vehicle code is called | ||
116 | // once per simulation step, its constants need to be scaled by this. | ||
117 | public float LastSimulatedTimestep { get; private set; } | ||
118 | |||
119 | // A value of the time now so all the collision and update routines do not have to get their own | 113 | // A value of the time now so all the collision and update routines do not have to get their own |
120 | // Set to 'now' just before all the prims and actors are called for collisions and updates | 114 | // Set to 'now' just before all the prims and actors are called for collisions and updates |
121 | public int SimulationNowTime { get; private set; } | 115 | public int SimulationNowTime { get; private set; } |
@@ -132,8 +126,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
132 | private EntityProperties[] m_updateArray; | 126 | private EntityProperties[] m_updateArray; |
133 | private GCHandle m_updateArrayPinnedHandle; | 127 | private GCHandle m_updateArrayPinnedHandle; |
134 | 128 | ||
135 | private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed | 129 | public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed |
136 | private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes | 130 | public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes |
137 | 131 | ||
138 | public float PID_D { get; private set; } // derivative | 132 | public float PID_D { get; private set; } // derivative |
139 | public float PID_P { get; private set; } // proportional | 133 | public float PID_P { get; private set; } // proportional |
@@ -153,6 +147,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
153 | { | 147 | { |
154 | get { return new Vector3(0f, 0f, Params.gravity); } | 148 | get { return new Vector3(0f, 0f, Params.gravity); } |
155 | } | 149 | } |
150 | // Just the Z value of the gravity | ||
151 | public float DefaultGravityZ | ||
152 | { | ||
153 | get { return Params.gravity; } | ||
154 | } | ||
156 | 155 | ||
157 | public float MaximumObjectMass { get; private set; } | 156 | public float MaximumObjectMass { get; private set; } |
158 | 157 | ||
@@ -171,8 +170,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
171 | callback = c; | 170 | callback = c; |
172 | } | 171 | } |
173 | } | 172 | } |
173 | private Object _taintLock = new Object(); // lock for using the next object | ||
174 | private List<TaintCallbackEntry> _taintedObjects; | 174 | private List<TaintCallbackEntry> _taintedObjects; |
175 | private Object _taintLock = new Object(); | ||
176 | 175 | ||
177 | // A pointer to an instance if this structure is passed to the C++ code | 176 | // A pointer to an instance if this structure is passed to the C++ code |
178 | // Used to pass basic configuration values to the unmanaged code. | 177 | // Used to pass basic configuration values to the unmanaged code. |
@@ -465,12 +464,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
465 | int collidersCount = 0; | 464 | int collidersCount = 0; |
466 | IntPtr collidersPtr; | 465 | IntPtr collidersPtr; |
467 | 466 | ||
468 | LastSimulatedTimestep = timeStep; | ||
469 | |||
470 | // prevent simulation until we've been initialized | 467 | // prevent simulation until we've been initialized |
471 | if (!m_initialized) return 10.0f; | 468 | if (!m_initialized) return 5.0f; |
472 | |||
473 | int simulateStartTime = Util.EnvironmentTickCount(); | ||
474 | 469 | ||
475 | // update the prim states while we know the physics engine is not busy | 470 | // update the prim states while we know the physics engine is not busy |
476 | int numTaints = _taintedObjects.Count; | 471 | int numTaints = _taintedObjects.Count; |
@@ -478,6 +473,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
478 | 473 | ||
479 | // Some of the prims operate with special vehicle properties | 474 | // Some of the prims operate with special vehicle properties |
480 | ProcessVehicles(timeStep); | 475 | ProcessVehicles(timeStep); |
476 | numTaints += _taintedObjects.Count; | ||
481 | ProcessTaints(); // the vehicles might have added taints | 477 | ProcessTaints(); // the vehicles might have added taints |
482 | 478 | ||
483 | // step the physical world one interval | 479 | // step the physical world one interval |
@@ -506,6 +502,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
506 | // Get a value for 'now' so all the collision and update routines don't have to get their own | 502 | // Get a value for 'now' so all the collision and update routines don't have to get their own |
507 | SimulationNowTime = Util.EnvironmentTickCount(); | 503 | SimulationNowTime = Util.EnvironmentTickCount(); |
508 | 504 | ||
505 | // This is a kludge to get avatar movement updates. | ||
506 | // ODE sends collisions for avatars even if there are have been no collisions. This updates | ||
507 | // avatar animations and stuff. | ||
508 | // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. | ||
509 | m_objectsWithCollisions = new HashSet<BSPhysObject>(m_avatarsWithCollisions); | ||
510 | |||
509 | // If there were collisions, process them by sending the event to the prim. | 511 | // If there were collisions, process them by sending the event to the prim. |
510 | // Collisions must be processed before updates. | 512 | // Collisions must be processed before updates. |
511 | if (collidersCount > 0) | 513 | if (collidersCount > 0) |
@@ -527,13 +529,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
527 | bsp.SendCollisions(); | 529 | bsp.SendCollisions(); |
528 | m_objectsWithCollisions.Clear(); | 530 | m_objectsWithCollisions.Clear(); |
529 | 531 | ||
530 | // This is a kludge to get avatar movement updated. | ||
531 | // ODE sends collisions even if there are none and this is used to update | ||
532 | // avatar animations and stuff. | ||
533 | foreach (BSPhysObject bpo in m_avatarsWithCollisions) | ||
534 | bpo.SendCollisions(); | ||
535 | // m_avatarsWithCollisions.Clear(); | ||
536 | |||
537 | // If any of the objects had updated properties, tell the object it has been changed by the physics engine | 532 | // If any of the objects had updated properties, tell the object it has been changed by the physics engine |
538 | if (updatedEntityCount > 0) | 533 | if (updatedEntityCount > 0) |
539 | { | 534 | { |
@@ -544,7 +539,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
544 | if (PhysObjects.TryGetValue(entprop.ID, out pobj)) | 539 | if (PhysObjects.TryGetValue(entprop.ID, out pobj)) |
545 | { | 540 | { |
546 | pobj.UpdateProperties(entprop); | 541 | pobj.UpdateProperties(entprop); |
547 | continue; | ||
548 | } | 542 | } |
549 | } | 543 | } |
550 | } | 544 | } |
@@ -558,18 +552,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
558 | } | 552 | } |
559 | } | 553 | } |
560 | 554 | ||
561 | // this is a waste since the outside routine also calcuates the physics simulation | 555 | // The physics engine returns the number of milliseconds it simulated this call. |
562 | // period. TODO: There should be a way of computing physics frames from simulator computation. | 556 | // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. |
563 | // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); | 557 | // Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS. |
564 | // return (timeStep * (float)simulateTotalTime); | 558 | return numSubSteps * m_fixedTimeStep; |
565 | |||
566 | // TODO: FIX THIS: fps calculation possibly wrong. | ||
567 | // This calculation says 1/timeStep is the ideal frame rate. Any time added to | ||
568 | // that by the physics simulation gives a slower frame rate. | ||
569 | long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime); | ||
570 | if (totalSimulationTime >= timeStep) | ||
571 | return 0; | ||
572 | return 1f / (timeStep + totalSimulationTime); | ||
573 | } | 559 | } |
574 | 560 | ||
575 | // Something has collided | 561 | // Something has collided |
@@ -580,28 +566,25 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
580 | return; // don't send collisions to the terrain | 566 | return; // don't send collisions to the terrain |
581 | } | 567 | } |
582 | 568 | ||
583 | BSPhysObject collider = PhysObjects[localID]; | 569 | BSPhysObject collider; |
584 | // TODO: as of this code, terrain was not in the physical object list. | 570 | if (!PhysObjects.TryGetValue(localID, out collider)) |
585 | // When BSTerrain is created and it will be in the list, we can remove | ||
586 | // the possibility that it's not there and just fetch the collidee. | ||
587 | BSPhysObject collidee = null; | ||
588 | |||
589 | ActorTypes type = ActorTypes.Prim; | ||
590 | if (collidingWith <= TerrainManager.HighestTerrainID) | ||
591 | { | ||
592 | type = ActorTypes.Ground; | ||
593 | } | ||
594 | else | ||
595 | { | 571 | { |
596 | collidee = PhysObjects[collidingWith]; | 572 | // If the object that is colliding cannot be found, just ignore the collision. |
597 | if (collidee is BSCharacter) | 573 | return; |
598 | type = ActorTypes.Agent; | ||
599 | } | 574 | } |
600 | 575 | ||
576 | // The terrain is not in the physical object list so 'collidee' | ||
577 | // can be null when Collide() is called. | ||
578 | BSPhysObject collidee = null; | ||
579 | PhysObjects.TryGetValue(collidingWith, out collidee); | ||
580 | |||
601 | // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); | 581 | // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); |
602 | 582 | ||
603 | collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration); | 583 | if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) |
604 | m_objectsWithCollisions.Add(collider); | 584 | { |
585 | // If a collision was posted, remember to send it to the simulator | ||
586 | m_objectsWithCollisions.Add(collider); | ||
587 | } | ||
605 | 588 | ||
606 | return; | 589 | return; |
607 | } | 590 | } |
@@ -619,9 +602,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
619 | public override void SetWaterLevel(float baseheight) | 602 | public override void SetWaterLevel(float baseheight) |
620 | { | 603 | { |
621 | m_waterLevel = baseheight; | 604 | m_waterLevel = baseheight; |
622 | // TODO: pass to physics engine so things will float? | ||
623 | } | 605 | } |
624 | public float GetWaterLevel() | 606 | // Someday.... |
607 | public float GetWaterLevelAtXYZ(Vector3 loc) | ||
625 | { | 608 | { |
626 | return m_waterLevel; | 609 | return m_waterLevel; |
627 | } | 610 | } |
@@ -659,121 +642,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
659 | 642 | ||
660 | public override bool IsThreaded { get { return false; } } | 643 | public override bool IsThreaded { get { return false; } } |
661 | 644 | ||
662 | /// <summary> | ||
663 | /// Routine to figure out if we need to mesh this prim with our mesher | ||
664 | /// </summary> | ||
665 | /// <param name="pbs"></param> | ||
666 | /// <returns>true if the prim needs meshing</returns> | ||
667 | public bool NeedsMeshing(PrimitiveBaseShape pbs) | ||
668 | { | ||
669 | // most of this is redundant now as the mesher will return null if it cant mesh a prim | ||
670 | // but we still need to check for sculptie meshing being enabled so this is the most | ||
671 | // convenient place to do it for now... | ||
672 | |||
673 | // int iPropertiesNotSupportedDefault = 0; | ||
674 | |||
675 | if (pbs.SculptEntry && !_meshSculptedPrim) | ||
676 | { | ||
677 | // Render sculpties as boxes | ||
678 | return false; | ||
679 | } | ||
680 | |||
681 | // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since Bullet | ||
682 | // can use an internal representation for the prim | ||
683 | if (!_forceSimplePrimMeshing) | ||
684 | { | ||
685 | if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) | ||
686 | || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 | ||
687 | && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)) | ||
688 | { | ||
689 | |||
690 | if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 | ||
691 | && pbs.ProfileHollow == 0 | ||
692 | && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 | ||
693 | && pbs.PathBegin == 0 && pbs.PathEnd == 0 | ||
694 | && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 | ||
695 | && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 | ||
696 | && pbs.PathShearX == 0 && pbs.PathShearY == 0) | ||
697 | { | ||
698 | return false; | ||
699 | } | ||
700 | } | ||
701 | } | ||
702 | |||
703 | /* TODO: verify that the mesher will now do all these shapes | ||
704 | if (pbs.ProfileHollow != 0) | ||
705 | iPropertiesNotSupportedDefault++; | ||
706 | |||
707 | if ((pbs.PathBegin != 0) || pbs.PathEnd != 0) | ||
708 | iPropertiesNotSupportedDefault++; | ||
709 | |||
710 | if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0)) | ||
711 | iPropertiesNotSupportedDefault++; | ||
712 | |||
713 | if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0) | ||
714 | iPropertiesNotSupportedDefault++; | ||
715 | |||
716 | if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100)) | ||
717 | iPropertiesNotSupportedDefault++; | ||
718 | |||
719 | if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0)) | ||
720 | iPropertiesNotSupportedDefault++; | ||
721 | |||
722 | if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) | ||
723 | iPropertiesNotSupportedDefault++; | ||
724 | |||
725 | 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)) | ||
726 | iPropertiesNotSupportedDefault++; | ||
727 | |||
728 | if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1) | ||
729 | iPropertiesNotSupportedDefault++; | ||
730 | |||
731 | // test for torus | ||
732 | if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square) | ||
733 | { | ||
734 | if (pbs.PathCurve == (byte)Extrusion.Curve1) | ||
735 | { | ||
736 | iPropertiesNotSupportedDefault++; | ||
737 | } | ||
738 | } | ||
739 | else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) | ||
740 | { | ||
741 | if (pbs.PathCurve == (byte)Extrusion.Straight) | ||
742 | { | ||
743 | iPropertiesNotSupportedDefault++; | ||
744 | } | ||
745 | // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits | ||
746 | else if (pbs.PathCurve == (byte)Extrusion.Curve1) | ||
747 | { | ||
748 | iPropertiesNotSupportedDefault++; | ||
749 | } | ||
750 | } | ||
751 | else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) | ||
752 | { | ||
753 | if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2) | ||
754 | { | ||
755 | iPropertiesNotSupportedDefault++; | ||
756 | } | ||
757 | } | ||
758 | else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | ||
759 | { | ||
760 | if (pbs.PathCurve == (byte)Extrusion.Straight) | ||
761 | { | ||
762 | iPropertiesNotSupportedDefault++; | ||
763 | } | ||
764 | else if (pbs.PathCurve == (byte)Extrusion.Curve1) | ||
765 | { | ||
766 | iPropertiesNotSupportedDefault++; | ||
767 | } | ||
768 | } | ||
769 | if (iPropertiesNotSupportedDefault == 0) | ||
770 | { | ||
771 | return false; | ||
772 | } | ||
773 | */ | ||
774 | return true; | ||
775 | } | ||
776 | |||
777 | // Calls to the PhysicsActors can't directly call into the physics engine | 645 | // Calls to the PhysicsActors can't directly call into the physics engine |
778 | // because it might be busy. We delay changes to a known time. | 646 | // because it might be busy. We delay changes to a known time. |
779 | // We rely on C#'s closure to save and restore the context for the delegate. | 647 | // We rely on C#'s closure to save and restore the context for the delegate. |
@@ -782,7 +650,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
782 | if (!m_initialized) return; | 650 | if (!m_initialized) return; |
783 | 651 | ||
784 | lock (_taintLock) | 652 | lock (_taintLock) |
653 | { | ||
785 | _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); | 654 | _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); |
655 | } | ||
656 | |||
786 | return; | 657 | return; |
787 | } | 658 | } |
788 | 659 | ||
@@ -919,14 +790,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
919 | { | 790 | { |
920 | new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", | 791 | new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", |
921 | ConfigurationParameters.numericTrue, | 792 | ConfigurationParameters.numericTrue, |
922 | (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, | 793 | (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, |
923 | (s) => { return s.NumericBool(s._meshSculptedPrim); }, | 794 | (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); }, |
924 | (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ), | 795 | (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ), |
925 | new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", | 796 | new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", |
926 | ConfigurationParameters.numericFalse, | 797 | ConfigurationParameters.numericFalse, |
927 | (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, | 798 | (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, |
928 | (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, | 799 | (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, |
929 | (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), | 800 | (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), |
930 | 801 | ||
931 | new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", | 802 | new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", |
932 | 8f, | 803 | 8f, |
@@ -1162,8 +1033,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1162 | (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, | 1033 | (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, |
1163 | (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, | 1034 | (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, |
1164 | (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), | 1035 | (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), |
1165 | new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=none, 1=all. Default=0", | 1036 | new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", |
1166 | 0.0f, | 1037 | 0.1f, |
1167 | (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, | 1038 | (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, |
1168 | (s) => { return s.m_params[0].linkConstraintCFM; }, | 1039 | (s) => { return s.m_params[0].linkConstraintCFM; }, |
1169 | (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), | 1040 | (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), |
@@ -1172,6 +1043,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1172 | (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, | 1043 | (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, |
1173 | (s) => { return s.m_params[0].linkConstraintERP; }, | 1044 | (s) => { return s.m_params[0].linkConstraintERP; }, |
1174 | (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), | 1045 | (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), |
1046 | new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", | ||
1047 | 40, | ||
1048 | (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); }, | ||
1049 | (s) => { return s.m_params[0].linkConstraintSolverIterations; }, | ||
1050 | (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ), | ||
1175 | 1051 | ||
1176 | new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", | 1052 | new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", |
1177 | 0f, | 1053 | 0f, |