diff options
author | UbitUmarov | 2017-09-05 20:25:12 +0100 |
---|---|---|
committer | UbitUmarov | 2017-09-05 20:25:12 +0100 |
commit | ca493a1bebfe544c31883fc8796ce1d05a4ed181 (patch) | |
tree | cb5583832fd78bae24ebb9e04559d9eb5bade896 /OpenSim/Region/PhysicsModules | |
parent | Merge branch 'master' into httptests (diff) | |
parent | BulletSim: Merge branch 'BulletSim2017' (diff) | |
download | opensim-SC-ca493a1bebfe544c31883fc8796ce1d05a4ed181.zip opensim-SC-ca493a1bebfe544c31883fc8796ce1d05a4ed181.tar.gz opensim-SC-ca493a1bebfe544c31883fc8796ce1d05a4ed181.tar.bz2 opensim-SC-ca493a1bebfe544c31883fc8796ce1d05a4ed181.tar.xz |
Merge branch 'master' into httptests
Diffstat (limited to 'OpenSim/Region/PhysicsModules')
12 files changed, 414 insertions, 86 deletions
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSAPIUnman.cs b/OpenSim/Region/PhysicsModules/BulletS/BSAPIUnman.cs index 42db7fe..840e453 100755 --- a/OpenSim/Region/PhysicsModules/BulletS/BSAPIUnman.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSAPIUnman.cs | |||
@@ -1405,6 +1405,19 @@ public override float GetMargin(BulletShape shape) | |||
1405 | } | 1405 | } |
1406 | 1406 | ||
1407 | // ===================================================================================== | 1407 | // ===================================================================================== |
1408 | // Raycast | ||
1409 | public override SweepHit ConvexSweepTest2(BulletWorld world, BulletBody sweepObject, Vector3 from, Vector3 to, float margin) { | ||
1410 | BulletWorldUnman worldu = world as BulletWorldUnman; | ||
1411 | BulletBodyUnman bodyu = sweepObject as BulletBodyUnman; | ||
1412 | return BSAPICPP.ConvexSweepTest2(worldu.ptr, bodyu.ptr, from, to, margin); | ||
1413 | } | ||
1414 | |||
1415 | public override RaycastHit RayTest2(BulletWorld world, Vector3 from, Vector3 to, uint filterGroup, uint filterMask) { | ||
1416 | BulletWorldUnman worldu = world as BulletWorldUnman; | ||
1417 | return BSAPICPP.RayTest2(worldu.ptr, from, to, filterGroup, filterMask); | ||
1418 | } | ||
1419 | |||
1420 | // ===================================================================================== | ||
1408 | // Debugging | 1421 | // Debugging |
1409 | public override void DumpRigidBody(BulletWorld world, BulletBody collisionObject) | 1422 | public override void DumpRigidBody(BulletWorld world, BulletBody collisionObject) |
1410 | { | 1423 | { |
@@ -2084,6 +2097,15 @@ public static extern void SetMargin2(IntPtr shape, float val); | |||
2084 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 2097 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
2085 | public static extern float GetMargin2(IntPtr shape); | 2098 | public static extern float GetMargin2(IntPtr shape); |
2086 | 2099 | ||
2100 | |||
2101 | // ===================================================================================== | ||
2102 | // Raycast | ||
2103 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
2104 | public static extern SweepHit ConvexSweepTest2(IntPtr sim, IntPtr obj, Vector3 from, Vector3 to, float margin); | ||
2105 | |||
2106 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
2107 | public static extern RaycastHit RayTest2(IntPtr sim, Vector3 from, Vector3 to, uint filterGroup, uint filterMask); | ||
2108 | |||
2087 | // ===================================================================================== | 2109 | // ===================================================================================== |
2088 | // Debugging | 2110 | // Debugging |
2089 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 2111 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSAPIXNA.cs b/OpenSim/Region/PhysicsModules/BulletS/BSAPIXNA.cs index 37017b0..7d58728 100755 --- a/OpenSim/Region/PhysicsModules/BulletS/BSAPIXNA.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSAPIXNA.cs | |||
@@ -2459,6 +2459,14 @@ private sealed class BulletConstraintXNA : BulletConstraint | |||
2459 | } | 2459 | } |
2460 | return false; | 2460 | return false; |
2461 | } | 2461 | } |
2462 | |||
2463 | public override SweepHit ConvexSweepTest2(BulletWorld world, BulletBody obj, Vector3 from, Vector3 to, float margin) { | ||
2464 | return new SweepHit(); | ||
2465 | } | ||
2466 | |||
2467 | public override RaycastHit RayTest2(BulletWorld world, Vector3 from, Vector3 to, uint filterGroup, uint filterMask) { | ||
2468 | return new RaycastHit(); | ||
2469 | } | ||
2462 | } | 2470 | } |
2463 | 2471 | ||
2464 | 2472 | ||
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSApiTemplate.cs b/OpenSim/Region/PhysicsModules/BulletS/BSApiTemplate.cs index 816189f..a288048 100644 --- a/OpenSim/Region/PhysicsModules/BulletS/BSApiTemplate.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSApiTemplate.cs | |||
@@ -121,6 +121,14 @@ public struct SweepHit | |||
121 | public float Fraction; | 121 | public float Fraction; |
122 | public Vector3 Normal; | 122 | public Vector3 Normal; |
123 | public Vector3 Point; | 123 | public Vector3 Point; |
124 | |||
125 | public bool hasHit() | ||
126 | { | ||
127 | float sum = Fraction | ||
128 | + Normal.X + Normal.Y + Normal.Z | ||
129 | + Point.X + Point.Y + Point.Z; | ||
130 | return (sum != 0) || (ID != 0); | ||
131 | } | ||
124 | } | 132 | } |
125 | [StructLayout(LayoutKind.Sequential)] | 133 | [StructLayout(LayoutKind.Sequential)] |
126 | public struct RaycastHit | 134 | public struct RaycastHit |
@@ -128,6 +136,13 @@ public struct RaycastHit | |||
128 | public UInt32 ID; | 136 | public UInt32 ID; |
129 | public float Fraction; | 137 | public float Fraction; |
130 | public Vector3 Normal; | 138 | public Vector3 Normal; |
139 | public Vector3 Point; | ||
140 | |||
141 | public bool hasHit() | ||
142 | { | ||
143 | float sum = Normal.X + Normal.Y + Normal.Z + Point.X + Point.Y + Point.Z; | ||
144 | return (sum != 0); | ||
145 | } | ||
131 | } | 146 | } |
132 | [StructLayout(LayoutKind.Sequential)] | 147 | [StructLayout(LayoutKind.Sequential)] |
133 | public struct CollisionDesc | 148 | public struct CollisionDesc |
@@ -742,6 +757,12 @@ public abstract void SetMargin(BulletShape shape, float val); | |||
742 | public abstract float GetMargin(BulletShape shape); | 757 | public abstract float GetMargin(BulletShape shape); |
743 | 758 | ||
744 | // ===================================================================================== | 759 | // ===================================================================================== |
760 | // Raycast | ||
761 | public abstract SweepHit ConvexSweepTest2(BulletWorld world, BulletBody obj, Vector3 from, Vector3 to, float margin); | ||
762 | |||
763 | public abstract RaycastHit RayTest2(BulletWorld world, Vector3 from, Vector3 to, uint filterGroup, uint filterMask); | ||
764 | |||
765 | // ===================================================================================== | ||
745 | // Debugging | 766 | // Debugging |
746 | public virtual void DumpRigidBody(BulletWorld sim, BulletBody collisionObject) { } | 767 | public virtual void DumpRigidBody(BulletWorld sim, BulletBody collisionObject) { } |
747 | 768 | ||
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs index 57f03fb..7faee70 100644 --- a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs | |||
@@ -496,8 +496,7 @@ public sealed class BSCharacter : BSPhysObject | |||
496 | public override OMV.Vector3 ForceVelocity { | 496 | public override OMV.Vector3 ForceVelocity { |
497 | get { return RawVelocity; } | 497 | get { return RawVelocity; } |
498 | set { | 498 | set { |
499 | PhysScene.AssertInTaintTime("BSCharacter.ForceVelocity"); | 499 | DetailLog("{0},BSCharacter.ForceVelocity.set={1}", LocalID, value); |
500 | DetailLog("{0}: BSCharacter.ForceVelocity.set = {1}", LocalID, value); | ||
501 | 500 | ||
502 | RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity); | 501 | RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity); |
503 | PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity); | 502 | PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity); |
@@ -638,8 +637,6 @@ public sealed class BSCharacter : BSPhysObject | |||
638 | public override float ForceBuoyancy { | 637 | public override float ForceBuoyancy { |
639 | get { return _buoyancy; } | 638 | get { return _buoyancy; } |
640 | set { | 639 | set { |
641 | PhysScene.AssertInTaintTime("BSCharacter.ForceBuoyancy"); | ||
642 | |||
643 | _buoyancy = value; | 640 | _buoyancy = value; |
644 | DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | 641 | DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
645 | // Buoyancy is faked by changing the gravity applied to the object | 642 | // Buoyancy is faked by changing the gravity applied to the object |
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSLinksetCompound.cs b/OpenSim/Region/PhysicsModules/BulletS/BSLinksetCompound.cs index 953ddee..dc390b2 100755 --- a/OpenSim/Region/PhysicsModules/BulletS/BSLinksetCompound.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSLinksetCompound.cs | |||
@@ -450,6 +450,7 @@ public sealed class BSLinksetCompound : BSLinkset | |||
450 | m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, LinksetRoot.PhysBody); | 450 | m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, LinksetRoot.PhysBody); |
451 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addBody,body={1},shape={2}", | 451 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addBody,body={1},shape={2}", |
452 | LinksetRoot.LocalID, LinksetRoot.PhysBody, linksetShape); | 452 | LinksetRoot.LocalID, LinksetRoot.PhysBody, linksetShape); |
453 | m_physicsScene.PE.ResetBroadphasePool(m_physicsScene.World); // DEBUG DEBUG | ||
453 | 454 | ||
454 | // With all of the linkset packed into the root prim, it has the mass of everyone. | 455 | // With all of the linkset packed into the root prim, it has the mass of everyone. |
455 | LinksetMass = ComputeLinksetMass(); | 456 | LinksetMass = ComputeLinksetMass(); |
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs b/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs index 352c03e..fcda92c 100755 --- a/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs | |||
@@ -230,6 +230,8 @@ public static class BSParam | |||
230 | public static float LinkConstraintCFM { get; private set; } | 230 | public static float LinkConstraintCFM { get; private set; } |
231 | public static float LinkConstraintSolverIterations { get; private set; } | 231 | public static float LinkConstraintSolverIterations { get; private set; } |
232 | 232 | ||
233 | public static bool UseBulletRaycast { get; private set; } | ||
234 | |||
233 | public static float PID_D { get; private set; } // derivative | 235 | public static float PID_D { get; private set; } // derivative |
234 | public static float PID_P { get; private set; } // proportional | 236 | public static float PID_P { get; private set; } // proportional |
235 | 237 | ||
@@ -823,6 +825,9 @@ public static class BSParam | |||
823 | new ParameterDefn<float>("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", | 825 | new ParameterDefn<float>("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", |
824 | 40 ), | 826 | 40 ), |
825 | 827 | ||
828 | new ParameterDefn<bool>("UseBulletRaycast", "If 'true', use the raycast function of the Bullet physics engine", | ||
829 | true ), | ||
830 | |||
826 | new ParameterDefn<float>("DebugNumber", "A console setable number sometimes used for debugging", | 831 | new ParameterDefn<float>("DebugNumber", "A console setable number sometimes used for debugging", |
827 | 1.0f ), | 832 | 1.0f ), |
828 | 833 | ||
@@ -833,7 +838,7 @@ public static class BSParam | |||
833 | new ParameterDefn<float>("ResetBroadphasePool", "Setting this is any value resets the broadphase collision pool", | 838 | new ParameterDefn<float>("ResetBroadphasePool", "Setting this is any value resets the broadphase collision pool", |
834 | 0f, | 839 | 0f, |
835 | (s) => { return 0f; }, | 840 | (s) => { return 0f; }, |
836 | (s,v) => { BSParam.ResetBroadphasePoolTainted(s, v, false /* inTaintTime */); } ), | 841 | (s,v) => { BSParam.ResetBroadphasePoolTainted(s, v); } ), |
837 | new ParameterDefn<float>("ResetConstraintSolver", "Setting this is any value resets the constraint solver", | 842 | new ParameterDefn<float>("ResetConstraintSolver", "Setting this is any value resets the constraint solver", |
838 | 0f, | 843 | 0f, |
839 | (s) => { return 0f; }, | 844 | (s) => { return 0f; }, |
@@ -919,10 +924,10 @@ public static class BSParam | |||
919 | // ===================================================================== | 924 | // ===================================================================== |
920 | // There are parameters that, when set, cause things to happen in the physics engine. | 925 | // There are parameters that, when set, cause things to happen in the physics engine. |
921 | // This causes the broadphase collision cache to be cleared. | 926 | // This causes the broadphase collision cache to be cleared. |
922 | private static void ResetBroadphasePoolTainted(BSScene pPhysScene, float v, bool inTaintTime) | 927 | private static void ResetBroadphasePoolTainted(BSScene pPhysScene, float v) |
923 | { | 928 | { |
924 | BSScene physScene = pPhysScene; | 929 | BSScene physScene = pPhysScene; |
925 | physScene.TaintedObject(inTaintTime, "BSParam.ResetBroadphasePoolTainted", delegate() | 930 | physScene.TaintedObject(BSScene.DetailLogZero, "BSParam.ResetBroadphasePoolTainted", delegate() |
926 | { | 931 | { |
927 | physScene.PE.ResetBroadphasePool(physScene.World); | 932 | physScene.PE.ResetBroadphasePool(physScene.World); |
928 | }); | 933 | }); |
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs b/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs index b153761..f085d70 100644 --- a/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs | |||
@@ -790,8 +790,6 @@ public class BSPrim : BSPhysObject | |||
790 | public override OMV.Vector3 ForceVelocity { | 790 | public override OMV.Vector3 ForceVelocity { |
791 | get { return RawVelocity; } | 791 | get { return RawVelocity; } |
792 | set { | 792 | set { |
793 | PhysScene.AssertInTaintTime("BSPrim.ForceVelocity"); | ||
794 | |||
795 | RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity); | 793 | RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity); |
796 | if (PhysBody.HasPhysicalBody) | 794 | if (PhysBody.HasPhysicalBody) |
797 | { | 795 | { |
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSPrimDisplaced.cs b/OpenSim/Region/PhysicsModules/BulletS/BSPrimDisplaced.cs index d8ed56b..3f90fc5 100755 --- a/OpenSim/Region/PhysicsModules/BulletS/BSPrimDisplaced.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSPrimDisplaced.cs | |||
@@ -81,7 +81,6 @@ public class BSPrimDisplaced : BSPrim | |||
81 | // Called at taint time. | 81 | // Called at taint time. |
82 | public virtual Vector3 SetEffectiveCenterOfMassDisplacement(Vector3 centerOfMassDisplacement) | 82 | public virtual Vector3 SetEffectiveCenterOfMassDisplacement(Vector3 centerOfMassDisplacement) |
83 | { | 83 | { |
84 | PhysScene.AssertInTaintTime("BSPrimDisplaced.SetEffectiveCenterOfMassDisplacement"); | ||
85 | Vector3 comDisp; | 84 | Vector3 comDisp; |
86 | if (UserSetCenterOfMassDisplacement.HasValue) | 85 | if (UserSetCenterOfMassDisplacement.HasValue) |
87 | comDisp = (OMV.Vector3)UserSetCenterOfMassDisplacement; | 86 | comDisp = (OMV.Vector3)UserSetCenterOfMassDisplacement; |
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs b/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs index 7ff0a07..163efaa 100644 --- a/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs | |||
@@ -124,9 +124,10 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
124 | // True if initialized and ready to do simulation steps | 124 | // True if initialized and ready to do simulation steps |
125 | private bool m_initialized = false; | 125 | private bool m_initialized = false; |
126 | 126 | ||
127 | // Flag which is true when processing taints. | 127 | // Object locked whenever execution is inside the physics engine |
128 | // Not guaranteed to be correct all the time (don't depend on this) but good for debugging. | 128 | public Object PhysicsEngineLock = new object(); |
129 | public bool InTaintTime { get; private set; } | 129 | // Flag that is true when the simulator is active and shouldn't be touched |
130 | public bool InSimulationTime { get; private set; } | ||
130 | 131 | ||
131 | // Pinned memory used to pass step information between managed and unmanaged | 132 | // Pinned memory used to pass step information between managed and unmanaged |
132 | internal int m_maxCollisionsPerFrame; | 133 | internal int m_maxCollisionsPerFrame; |
@@ -344,7 +345,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
344 | // Put some informational messages into the log file. | 345 | // Put some informational messages into the log file. |
345 | m_log.InfoFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation); | 346 | m_log.InfoFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation); |
346 | 347 | ||
347 | InTaintTime = false; | 348 | InSimulationTime = false; |
348 | m_initialized = true; | 349 | m_initialized = true; |
349 | 350 | ||
350 | // If the physics engine runs on its own thread, start same. | 351 | // If the physics engine runs on its own thread, start same. |
@@ -657,48 +658,57 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
657 | 658 | ||
658 | int beforeTime = Util.EnvironmentTickCount(); | 659 | int beforeTime = Util.EnvironmentTickCount(); |
659 | int simTime = 0; | 660 | int simTime = 0; |
661 | int numTaints = 0; | ||
662 | int numSubSteps = 0; | ||
660 | 663 | ||
661 | int numTaints = _taintOperations.Count; | 664 | lock (PhysicsEngineLock) |
662 | InTaintTime = true; // Only used for debugging so locking is not necessary. | 665 | { |
666 | InSimulationTime = true; | ||
667 | // update the prim states while we know the physics engine is not busy | ||
668 | numTaints += ProcessTaints(); | ||
663 | 669 | ||
664 | // update the prim states while we know the physics engine is not busy | 670 | // Some of the physical objects requre individual, pre-step calls |
665 | ProcessTaints(); | 671 | // (vehicles and avatar movement, in particular) |
672 | TriggerPreStepEvent(timeStep); | ||
666 | 673 | ||
667 | // Some of the physical objects requre individual, pre-step calls | 674 | // the prestep actions might have added taints |
668 | // (vehicles and avatar movement, in particular) | 675 | numTaints += ProcessTaints(); |
669 | TriggerPreStepEvent(timeStep); | ||
670 | 676 | ||
671 | // the prestep actions might have added taints | 677 | // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. |
672 | numTaints += _taintOperations.Count; | 678 | // Only enable this in a limited test world with few objects. |
673 | ProcessTaints(); | 679 | if (m_physicsPhysicalDumpEnabled) |
680 | PE.DumpAllInfo(World); | ||
674 | 681 | ||
675 | InTaintTime = false; // Only used for debugging so locking is not necessary. | 682 | // step the physical world one interval |
683 | m_simulationStep++; | ||
684 | try | ||
685 | { | ||
686 | numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount); | ||
687 | } | ||
688 | catch (Exception e) | ||
689 | { | ||
690 | m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}", | ||
691 | LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e); | ||
692 | DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}", | ||
693 | DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); | ||
694 | updatedEntityCount = 0; | ||
695 | collidersCount = 0; | ||
696 | } | ||
676 | 697 | ||
677 | // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. | 698 | // Make the physics engine dump useful statistics periodically |
678 | // Only enable this in a limited test world with few objects. | 699 | if (PhysicsMetricDumpFrames != 0 && ((m_simulationStep % PhysicsMetricDumpFrames) == 0)) |
679 | if (m_physicsPhysicalDumpEnabled) | 700 | PE.DumpPhysicsStatistics(World); |
680 | PE.DumpAllInfo(World); | ||
681 | 701 | ||
682 | // step the physical world one interval | 702 | InSimulationTime = false; |
683 | m_simulationStep++; | 703 | |
684 | int numSubSteps = 0; | 704 | // Some actors want to know when the simulation step is complete. |
685 | try | 705 | TriggerPostStepEvent(timeStep); |
686 | { | 706 | |
687 | numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount); | 707 | // In case there were any parameter updates that happened during the simulation step |
688 | } | 708 | numTaints += ProcessTaints(); |
689 | catch (Exception e) | ||
690 | { | ||
691 | m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}", | ||
692 | LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e); | ||
693 | DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}", | ||
694 | DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); | ||
695 | updatedEntityCount = 0; | ||
696 | collidersCount = 0; | ||
697 | } | ||
698 | 709 | ||
699 | // Make the physics engine dump useful statistics periodically | 710 | InSimulationTime = false; |
700 | if (PhysicsMetricDumpFrames != 0 && ((m_simulationStep % PhysicsMetricDumpFrames) == 0)) | 711 | } |
701 | PE.DumpPhysicsStatistics(World); | ||
702 | 712 | ||
703 | // Get a value for 'now' so all the collision and update routines don't have to get their own. | 713 | // Get a value for 'now' so all the collision and update routines don't have to get their own. |
704 | SimulationNowTime = Util.EnvironmentTickCount(); | 714 | SimulationNowTime = Util.EnvironmentTickCount(); |
@@ -748,9 +758,6 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
748 | } | 758 | } |
749 | } | 759 | } |
750 | 760 | ||
751 | // Some actors want to know when the simulation step is complete. | ||
752 | TriggerPostStepEvent(timeStep); | ||
753 | |||
754 | simTime = Util.EnvironmentTickCountSubtract(beforeTime); | 761 | simTime = Util.EnvironmentTickCountSubtract(beforeTime); |
755 | if (PhysicsLogging.Enabled) | 762 | if (PhysicsLogging.Enabled) |
756 | { | 763 | { |
@@ -956,6 +963,149 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
956 | 963 | ||
957 | #endregion // Terrain | 964 | #endregion // Terrain |
958 | 965 | ||
966 | #region Raycast | ||
967 | |||
968 | public override bool SupportsRayCast() | ||
969 | { | ||
970 | return BSParam.UseBulletRaycast; | ||
971 | } | ||
972 | |||
973 | public override bool SupportsRaycastWorldFiltered() | ||
974 | { | ||
975 | return BSParam.UseBulletRaycast; | ||
976 | } | ||
977 | |||
978 | |||
979 | /// <summary> | ||
980 | /// Queue a raycast against the physics scene. | ||
981 | /// The provided callback method will be called when the raycast is complete | ||
982 | /// | ||
983 | /// Many physics engines don't support collision testing at the same time as | ||
984 | /// manipulating the physics scene, so we queue the request up and callback | ||
985 | /// a custom method when the raycast is complete. | ||
986 | /// This allows physics engines that give an immediate result to callback immediately | ||
987 | /// and ones that don't, to callback when it gets a result back. | ||
988 | /// public delegate void RayCallback(List<ContactResult> list); | ||
989 | /// | ||
990 | /// ODE for example will not allow you to change the scene while collision testing or | ||
991 | /// it asserts, 'opteration not valid for locked space'. This includes adding a ray to the scene. | ||
992 | /// | ||
993 | /// This is named RayCastWorld to not conflict with modrex's Raycast method. | ||
994 | /// </summary> | ||
995 | /// <param name="position">Origin of the ray</param> | ||
996 | /// <param name="direction">Direction of the ray</param> | ||
997 | /// <param name="length">Length of ray in meters</param> | ||
998 | /// <param name="retMethod">Method to call when the raycast is complete</param> | ||
999 | public override void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) | ||
1000 | { | ||
1001 | if (retMethod != null) | ||
1002 | { | ||
1003 | if (BSParam.UseBulletRaycast) | ||
1004 | { | ||
1005 | Vector3 posFrom = position; | ||
1006 | Vector3 posTo = Vector3.Normalize(direction) * length + position; | ||
1007 | |||
1008 | TaintedObject(DetailLogZero, "BSScene.RaycastWorld1", delegate () | ||
1009 | { | ||
1010 | RaycastHit hitInfo = PE.RayTest2(World, posFrom, posTo, 0xffff, 0xffff); | ||
1011 | retMethod(true, hitInfo.Point, hitInfo.ID, hitInfo.Fraction, hitInfo.Normal); | ||
1012 | }); | ||
1013 | } | ||
1014 | else | ||
1015 | { | ||
1016 | retMethod(false, Vector3.Zero, 0, 999999999999f, Vector3.Zero); | ||
1017 | } | ||
1018 | } | ||
1019 | } | ||
1020 | |||
1021 | public override void RaycastWorld(Vector3 position, Vector3 direction, float length, int count, RayCallback retMethod) | ||
1022 | { | ||
1023 | if (retMethod != null) | ||
1024 | { | ||
1025 | if (BSParam.UseBulletRaycast) | ||
1026 | { | ||
1027 | List<ContactResult> hitInfo = RaycastWorld(position, direction, length, count); | ||
1028 | retMethod(hitInfo); | ||
1029 | } | ||
1030 | else | ||
1031 | { | ||
1032 | retMethod(new List<ContactResult>()); | ||
1033 | } | ||
1034 | } | ||
1035 | } | ||
1036 | |||
1037 | public override List<ContactResult> RaycastWorld(Vector3 position, Vector3 direction, float length, int count) | ||
1038 | { | ||
1039 | return (List<ContactResult>)RaycastWorld(position, direction, length, count, RayFilterFlags.All); | ||
1040 | } | ||
1041 | |||
1042 | public override object RaycastWorld(Vector3 position, Vector3 direction, float length, int count, RayFilterFlags filter) | ||
1043 | { | ||
1044 | List<ContactResult> ret = new List<ContactResult>(); | ||
1045 | if (BSParam.UseBulletRaycast) | ||
1046 | { | ||
1047 | uint collisionFilter = 0; | ||
1048 | uint collisionMask = 0; | ||
1049 | if ((filter & RayFilterFlags.land) != 0) | ||
1050 | { | ||
1051 | collisionFilter |= BulletSimData.CollisionTypeMasks[CollisionType.Terrain].group; | ||
1052 | collisionMask |= BulletSimData.CollisionTypeMasks[CollisionType.Terrain].mask; | ||
1053 | } | ||
1054 | if ((filter & RayFilterFlags.agent) != 0) | ||
1055 | { | ||
1056 | collisionFilter |= BulletSimData.CollisionTypeMasks[CollisionType.Avatar].group; | ||
1057 | collisionMask |= BulletSimData.CollisionTypeMasks[CollisionType.Avatar].mask; | ||
1058 | } | ||
1059 | if ((filter & RayFilterFlags.nonphysical) != 0) | ||
1060 | { | ||
1061 | collisionFilter |= BulletSimData.CollisionTypeMasks[CollisionType.Static].group; | ||
1062 | collisionMask |= BulletSimData.CollisionTypeMasks[CollisionType.Static].mask; | ||
1063 | } | ||
1064 | if ((filter & RayFilterFlags.physical) != 0) | ||
1065 | { | ||
1066 | collisionFilter |= BulletSimData.CollisionTypeMasks[CollisionType.Dynamic].group; | ||
1067 | collisionMask |= BulletSimData.CollisionTypeMasks[CollisionType.Dynamic].mask; | ||
1068 | } | ||
1069 | // if ((filter & RayFilterFlags.phantom) != 0) | ||
1070 | // { | ||
1071 | // collisionFilter |= BulletSimData.CollisionTypeMasks[CollisionType.VolumeDetect].group; | ||
1072 | // collisionMask |= BulletSimData.CollisionTypeMasks[CollisionType.VolumeDetect].mask; | ||
1073 | // } | ||
1074 | if ((filter & RayFilterFlags.volumedtc) != 0) | ||
1075 | { | ||
1076 | collisionFilter |= BulletSimData.CollisionTypeMasks[CollisionType.VolumeDetect].group; | ||
1077 | collisionMask |= BulletSimData.CollisionTypeMasks[CollisionType.VolumeDetect].mask; | ||
1078 | } | ||
1079 | DetailLog("{0},RaycastWorld,pos={1},dir={2},len={3},count={4},filter={5},filter={6},mask={7}", | ||
1080 | DetailLogZero, position, direction, length, count, filter, collisionFilter, collisionMask); | ||
1081 | // NOTE: locking ensures the physics engine is not executing. | ||
1082 | // The caller might have to wait for the physics engine to finish. | ||
1083 | lock (PhysicsEngineLock) | ||
1084 | { | ||
1085 | Vector3 posFrom = position; | ||
1086 | Vector3 posTo = Vector3.Normalize(direction) * length + position; | ||
1087 | DetailLog("{0},RaycastWorld,RayTest2,from={1},to={2}", | ||
1088 | DetailLogZero, posFrom, posTo); | ||
1089 | RaycastHit hitInfo = PE.RayTest2(World, posFrom, posTo, collisionFilter, collisionMask); | ||
1090 | if (hitInfo.hasHit()) | ||
1091 | { | ||
1092 | ContactResult result = new ContactResult(); | ||
1093 | result.Pos = hitInfo.Point; | ||
1094 | result.Normal = hitInfo.Normal; | ||
1095 | result.ConsumerID = hitInfo.ID; | ||
1096 | result.Depth = hitInfo.Fraction; | ||
1097 | ret.Add(result); | ||
1098 | DetailLog("{0},RaycastWorld,hit,pos={1},norm={2},depth={3},id={4}", | ||
1099 | DetailLogZero, result.Pos, result.Normal, result.Depth, result.ConsumerID); | ||
1100 | } | ||
1101 | } | ||
1102 | } | ||
1103 | return ret; | ||
1104 | } | ||
1105 | |||
1106 | #endregion Raycast | ||
1107 | |||
1108 | |||
959 | public override Dictionary<uint, float> GetTopColliders() | 1109 | public override Dictionary<uint, float> GetTopColliders() |
960 | { | 1110 | { |
961 | Dictionary<uint, float> topColliders; | 1111 | Dictionary<uint, float> topColliders; |
@@ -1068,32 +1218,35 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
1068 | // Calls to the PhysicsActors can't directly call into the physics engine | 1218 | // Calls to the PhysicsActors can't directly call into the physics engine |
1069 | // because it might be busy. We delay changes to a known time. | 1219 | // because it might be busy. We delay changes to a known time. |
1070 | // We rely on C#'s closure to save and restore the context for the delegate. | 1220 | // We rely on C#'s closure to save and restore the context for the delegate. |
1071 | public void TaintedObject(string pOriginator, string pIdent, TaintCallback pCallback) | 1221 | // NOTE: 'inTaintTime' is no longer used. This entry exists so all the calls don't have to be changed. |
1222 | // public void TaintedObject(bool inTaintTime, String pIdent, TaintCallback pCallback) | ||
1223 | // { | ||
1224 | // TaintedObject(BSScene.DetailLogZero, pIdent, pCallback); | ||
1225 | // } | ||
1226 | // NOTE: 'inTaintTime' is no longer used. This entry exists so all the calls don't have to be changed. | ||
1227 | public void TaintedObject(bool inTaintTime, uint pOriginator, String pIdent, TaintCallback pCallback) | ||
1072 | { | 1228 | { |
1073 | TaintedObject(false /*inTaintTime*/, pOriginator, pIdent, pCallback); | 1229 | TaintedObject(m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback); |
1074 | } | 1230 | } |
1075 | public void TaintedObject(uint pOriginator, String pIdent, TaintCallback pCallback) | 1231 | public void TaintedObject(uint pOriginator, String pIdent, TaintCallback pCallback) |
1076 | { | 1232 | { |
1077 | TaintedObject(false /*inTaintTime*/, m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback); | 1233 | TaintedObject(m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback); |
1078 | } | ||
1079 | public void TaintedObject(bool inTaintTime, String pIdent, TaintCallback pCallback) | ||
1080 | { | ||
1081 | TaintedObject(inTaintTime, BSScene.DetailLogZero, pIdent, pCallback); | ||
1082 | } | ||
1083 | public void TaintedObject(bool inTaintTime, uint pOriginator, String pIdent, TaintCallback pCallback) | ||
1084 | { | ||
1085 | TaintedObject(inTaintTime, m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback); | ||
1086 | } | 1234 | } |
1087 | // Sometimes a potentially tainted operation can be used in and out of taint time. | 1235 | // Sometimes a potentially tainted operation can be used in and out of taint time. |
1088 | // This routine executes the command immediately if in taint-time otherwise it is queued. | 1236 | // This routine executes the command immediately if in taint-time otherwise it is queued. |
1089 | public void TaintedObject(bool inTaintTime, string pOriginator, string pIdent, TaintCallback pCallback) | 1237 | public void TaintedObject(string pOriginator, string pIdent, TaintCallback pCallback) |
1090 | { | 1238 | { |
1091 | if (!m_initialized) return; | 1239 | if (!m_initialized) return; |
1092 | 1240 | ||
1093 | if (inTaintTime) | 1241 | if (Monitor.TryEnter(PhysicsEngineLock)) |
1242 | { | ||
1243 | // If we can get exclusive access to the physics engine, just do the operation | ||
1094 | pCallback(); | 1244 | pCallback(); |
1245 | Monitor.Exit(PhysicsEngineLock); | ||
1246 | } | ||
1095 | else | 1247 | else |
1096 | { | 1248 | { |
1249 | // The physics engine is busy, queue the operation | ||
1097 | lock (_taintLock) | 1250 | lock (_taintLock) |
1098 | { | 1251 | { |
1099 | _taintOperations.Add(new TaintCallbackEntry(pOriginator, pIdent, pCallback)); | 1252 | _taintOperations.Add(new TaintCallbackEntry(pOriginator, pIdent, pCallback)); |
@@ -1120,14 +1273,21 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
1120 | // When someone tries to change a property on a BSPrim or BSCharacter, the object queues | 1273 | // When someone tries to change a property on a BSPrim or BSCharacter, the object queues |
1121 | // a callback into itself to do the actual property change. That callback is called | 1274 | // a callback into itself to do the actual property change. That callback is called |
1122 | // here just before the physics engine is called to step the simulation. | 1275 | // here just before the physics engine is called to step the simulation. |
1123 | public void ProcessTaints() | 1276 | // Returns the number of taints processed |
1277 | // NOTE: Called while PhysicsEngineLock is locked | ||
1278 | public int ProcessTaints() | ||
1124 | { | 1279 | { |
1125 | ProcessRegularTaints(); | 1280 | int ret = 0; |
1126 | ProcessPostTaintTaints(); | 1281 | ret += ProcessRegularTaints(); |
1282 | ret += ProcessPostTaintTaints(); | ||
1283 | return ret; | ||
1127 | } | 1284 | } |
1128 | 1285 | ||
1129 | private void ProcessRegularTaints() | 1286 | // Returns the number of taints processed |
1287 | // NOTE: Called while PhysicsEngineLock is locked | ||
1288 | private int ProcessRegularTaints() | ||
1130 | { | 1289 | { |
1290 | int ret = 0; | ||
1131 | if (m_initialized && _taintOperations.Count > 0) // save allocating new list if there is nothing to process | 1291 | if (m_initialized && _taintOperations.Count > 0) // save allocating new list if there is nothing to process |
1132 | { | 1292 | { |
1133 | // swizzle a new list into the list location so we can process what's there | 1293 | // swizzle a new list into the list location so we can process what's there |
@@ -1144,6 +1304,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
1144 | { | 1304 | { |
1145 | DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", tcbe.originator, tcbe.ident); // DEBUG DEBUG DEBUG | 1305 | DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", tcbe.originator, tcbe.ident); // DEBUG DEBUG DEBUG |
1146 | tcbe.callback(); | 1306 | tcbe.callback(); |
1307 | ret++; | ||
1147 | } | 1308 | } |
1148 | catch (Exception e) | 1309 | catch (Exception e) |
1149 | { | 1310 | { |
@@ -1152,6 +1313,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
1152 | } | 1313 | } |
1153 | oldList.Clear(); | 1314 | oldList.Clear(); |
1154 | } | 1315 | } |
1316 | return ret; | ||
1155 | } | 1317 | } |
1156 | 1318 | ||
1157 | // Schedule an update to happen after all the regular taints are processed. | 1319 | // Schedule an update to happen after all the regular taints are processed. |
@@ -1170,8 +1332,11 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
1170 | } | 1332 | } |
1171 | 1333 | ||
1172 | // Taints that happen after the normal taint processing but before the simulation step. | 1334 | // Taints that happen after the normal taint processing but before the simulation step. |
1173 | private void ProcessPostTaintTaints() | 1335 | // Returns the number of taints processed |
1336 | // NOTE: Called while PhysicsEngineLock is locked | ||
1337 | private int ProcessPostTaintTaints() | ||
1174 | { | 1338 | { |
1339 | int ret = 0; | ||
1175 | if (m_initialized && _postTaintOperations.Count > 0) | 1340 | if (m_initialized && _postTaintOperations.Count > 0) |
1176 | { | 1341 | { |
1177 | Dictionary<string, TaintCallbackEntry> oldList; | 1342 | Dictionary<string, TaintCallbackEntry> oldList; |
@@ -1187,6 +1352,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
1187 | { | 1352 | { |
1188 | DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG | 1353 | DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG |
1189 | kvp.Value.callback(); | 1354 | kvp.Value.callback(); |
1355 | ret++; | ||
1190 | } | 1356 | } |
1191 | catch (Exception e) | 1357 | catch (Exception e) |
1192 | { | 1358 | { |
@@ -1195,20 +1361,8 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
1195 | } | 1361 | } |
1196 | oldList.Clear(); | 1362 | oldList.Clear(); |
1197 | } | 1363 | } |
1364 | return ret; | ||
1198 | } | 1365 | } |
1199 | |||
1200 | // Only used for debugging. Does not change state of anything so locking is not necessary. | ||
1201 | public bool AssertInTaintTime(string whereFrom) | ||
1202 | { | ||
1203 | if (!InTaintTime) | ||
1204 | { | ||
1205 | DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); | ||
1206 | m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); | ||
1207 | // Util.PrintCallStack(DetailLog); | ||
1208 | } | ||
1209 | return InTaintTime; | ||
1210 | } | ||
1211 | |||
1212 | #endregion // Taints | 1366 | #endregion // Taints |
1213 | 1367 | ||
1214 | #region IPhysicsParameters | 1368 | #region IPhysicsParameters |
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs b/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs index 4ec6f51..86bf23f 100755 --- a/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs | |||
@@ -75,8 +75,6 @@ public sealed class BSShapeCollection : IDisposable | |||
75 | // Called at taint-time. | 75 | // Called at taint-time. |
76 | public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim, PhysicalDestructionCallback bodyCallback) | 76 | public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim, PhysicalDestructionCallback bodyCallback) |
77 | { | 77 | { |
78 | m_physicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); | ||
79 | |||
80 | bool ret = false; | 78 | bool ret = false; |
81 | 79 | ||
82 | // This lock could probably be pushed down lower but building shouldn't take long | 80 | // This lock could probably be pushed down lower but building shouldn't take long |
@@ -229,6 +227,8 @@ public sealed class BSShapeCollection : IDisposable | |||
229 | ret = CreateGeomMeshOrHull(prim, shapeCallback); | 227 | ret = CreateGeomMeshOrHull(prim, shapeCallback); |
230 | } | 228 | } |
231 | 229 | ||
230 | m_physicsScene.PE.ResetBroadphasePool(m_physicsScene.World); // DEBUG DEBUG | ||
231 | |||
232 | return ret; | 232 | return ret; |
233 | } | 233 | } |
234 | 234 | ||
@@ -344,8 +344,6 @@ public sealed class BSShapeCollection : IDisposable | |||
344 | if (!body.HasPhysicalBody) | 344 | if (!body.HasPhysicalBody) |
345 | return; | 345 | return; |
346 | 346 | ||
347 | m_physicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody"); | ||
348 | |||
349 | lock (m_collectionActivityLock) | 347 | lock (m_collectionActivityLock) |
350 | { | 348 | { |
351 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body); | 349 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body); |
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BulletSimData.cs b/OpenSim/Region/PhysicsModules/BulletS/BulletSimData.cs index 3329395..308769b 100755 --- a/OpenSim/Region/PhysicsModules/BulletS/BulletSimData.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BulletSimData.cs | |||
@@ -100,6 +100,7 @@ public class BulletBody | |||
100 | } | 100 | } |
101 | } | 101 | } |
102 | 102 | ||
103 | // Handle to btCollisionObject - a shape that can be added to a btRidgidBody | ||
103 | public class BulletShape | 104 | public class BulletShape |
104 | { | 105 | { |
105 | public BulletShape() | 106 | public BulletShape() |
diff --git a/OpenSim/Region/PhysicsModules/BulletS/Tests/Raycast.cs b/OpenSim/Region/PhysicsModules/BulletS/Tests/Raycast.cs new file mode 100755 index 0000000..bfa95c1 --- /dev/null +++ b/OpenSim/Region/PhysicsModules/BulletS/Tests/Raycast.cs | |||
@@ -0,0 +1,124 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Linq; | ||
31 | using System.Text; | ||
32 | |||
33 | using NUnit.Framework; | ||
34 | using log4net; | ||
35 | |||
36 | using OpenSim.Framework; | ||
37 | using OpenSim.Region.PhysicsModule.BulletS; | ||
38 | using OpenSim.Region.PhysicsModules.SharedBase; | ||
39 | using OpenSim.Tests.Common; | ||
40 | |||
41 | using OpenMetaverse; | ||
42 | |||
43 | namespace OpenSim.Region.PhysicsModule.BulletS.Tests | ||
44 | { | ||
45 | [TestFixture] | ||
46 | public class BulletSimRaycast : OpenSimTestCase | ||
47 | { | ||
48 | // Documentation on attributes: http://www.nunit.org/index.php?p=attributes&r=2.6.1 | ||
49 | // Documentation on assertions: http://www.nunit.org/index.php?p=assertions&r=2.6.1 | ||
50 | |||
51 | BSScene _physicsScene { get; set; } | ||
52 | BSPrim _targetSphere { get; set; } | ||
53 | Vector3 _targetSpherePosition { get; set; } | ||
54 | float _simulationTimeStep = 0.089f; | ||
55 | |||
56 | uint _targetLocalID = 123; | ||
57 | |||
58 | [TestFixtureSetUp] | ||
59 | public void Init() | ||
60 | { | ||
61 | Dictionary<string, string> engineParams = new Dictionary<string, string>(); | ||
62 | engineParams.Add("UseBulletRaycast", "true"); | ||
63 | _physicsScene = BulletSimTestsUtil.CreateBasicPhysicsEngine(engineParams); | ||
64 | |||
65 | PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateSphere(); | ||
66 | Vector3 pos = new Vector3(100.0f, 100.0f, 50f); | ||
67 | _targetSpherePosition = pos; | ||
68 | Vector3 size = new Vector3(10f, 10f, 10f); | ||
69 | pbs.Scale = size; | ||
70 | Quaternion rot = Quaternion.Identity; | ||
71 | bool isPhys = false; | ||
72 | |||
73 | _physicsScene.AddPrimShape("TargetSphere", pbs, pos, size, rot, isPhys, _targetLocalID); | ||
74 | _targetSphere = (BSPrim)_physicsScene.PhysObjects[_targetLocalID]; | ||
75 | // The actual prim shape creation happens at taint time | ||
76 | _physicsScene.ProcessTaints(); | ||
77 | |||
78 | } | ||
79 | |||
80 | [TestFixtureTearDown] | ||
81 | public void TearDown() | ||
82 | { | ||
83 | if (_physicsScene != null) | ||
84 | { | ||
85 | // The Dispose() will also free any physical objects in the scene | ||
86 | _physicsScene.Dispose(); | ||
87 | _physicsScene = null; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | // There is a 10x10x10 sphere at <100,100,50> | ||
92 | // Shoot rays around the sphere and verify it hits and doesn't hit | ||
93 | // TestCase parameters are <x,y,z> of start and <x,y,z> of end and expected result | ||
94 | [TestCase(100f, 50f, 50f, 100f, 150f, 50f, true, "Pass through sphere from front")] | ||
95 | [TestCase(50f, 100f, 50f, 150f, 100f, 50f, true, "Pass through sphere from side")] | ||
96 | [TestCase(50f, 50f, 50f, 150f, 150f, 50f, true, "Pass through sphere diaginally")] | ||
97 | [TestCase(100f, 100f, 100f, 100f, 100f, 20f, true, "Pass through sphere from above")] | ||
98 | [TestCase(20f, 20f, 50f, 80f, 80f, 50f, false, "Not reach sphere")] | ||
99 | [TestCase(50f, 50f, 65f, 150f, 150f, 65f, false, "Passed over sphere")] | ||
100 | public void RaycastAroundObject(float fromX, float fromY, float fromZ, float toX, float toY, float toZ, bool expected, string msg) { | ||
101 | Vector3 fromPos = new Vector3(fromX, fromY, fromZ); | ||
102 | Vector3 toPos = new Vector3(toX, toY, toZ); | ||
103 | Vector3 direction = toPos - fromPos; | ||
104 | float len = Vector3.Distance(fromPos, toPos); | ||
105 | |||
106 | List<ContactResult> results = _physicsScene.RaycastWorld(fromPos, direction, len, 1); | ||
107 | |||
108 | if (expected) { | ||
109 | // The test coordinates should generate a hit | ||
110 | Assert.True(results.Count != 0, msg + ": Did not return a hit but expected to."); | ||
111 | Assert.True(results.Count == 1, msg + ": Raycast returned not just one hit result."); | ||
112 | Assert.True(results[0].ConsumerID == _targetLocalID, msg + ": Raycast returned a collision object other than the target"); | ||
113 | } | ||
114 | else | ||
115 | { | ||
116 | // The test coordinates should not generate a hit | ||
117 | if (results.Count > 0) | ||
118 | { | ||
119 | Assert.False(results.Count > 0, msg + ": Returned a hit at " + results[0].Pos.ToString()); | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | } \ No newline at end of file | ||