diff options
author | onefang | 2019-09-11 16:36:50 +1000 |
---|---|---|
committer | onefang | 2019-09-11 16:36:50 +1000 |
commit | 50cd1ffd32f69228e566f2b0b89f86ea0d9fe489 (patch) | |
tree | 52f2ab0c04f1a5d7d6ac5dc872981b4b156447e7 /OpenSim/Region/PhysicsModules/BulletS/BSScene.cs | |
parent | Renamed branch to SledjChisl. (diff) | |
parent | Bump to release flavour, build 0. (diff) | |
download | opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.zip opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.gz opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.bz2 opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.xz |
Merge branch 'SledjChisl'
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/PhysicsModules/BulletS/BSScene.cs | 329 |
1 files changed, 235 insertions, 94 deletions
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs b/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs index 452ce55..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; |
@@ -212,6 +213,11 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
212 | get { return "BulletSim"; } | 213 | get { return "BulletSim"; } |
213 | } | 214 | } |
214 | 215 | ||
216 | public string Version | ||
217 | { | ||
218 | get { return "1.0"; } | ||
219 | } | ||
220 | |||
215 | public Type ReplaceableInterface | 221 | public Type ReplaceableInterface |
216 | { | 222 | { |
217 | get { return null; } | 223 | get { return null; } |
@@ -245,6 +251,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
245 | EngineType = Name; | 251 | EngineType = Name; |
246 | RegionName = scene.RegionInfo.RegionName; | 252 | RegionName = scene.RegionInfo.RegionName; |
247 | PhysicsSceneName = EngineType + "/" + RegionName; | 253 | PhysicsSceneName = EngineType + "/" + RegionName; |
254 | EngineName = Name + " " + Version; | ||
248 | 255 | ||
249 | scene.RegisterModuleInterface<PhysicsScene>(this); | 256 | scene.RegisterModuleInterface<PhysicsScene>(this); |
250 | Vector3 extent = new Vector3(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY, scene.RegionInfo.RegionSizeZ); | 257 | Vector3 extent = new Vector3(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY, scene.RegionInfo.RegionSizeZ); |
@@ -338,19 +345,19 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
338 | // Put some informational messages into the log file. | 345 | // Put some informational messages into the log file. |
339 | 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); |
340 | 347 | ||
341 | InTaintTime = false; | 348 | InSimulationTime = false; |
342 | m_initialized = true; | 349 | m_initialized = true; |
343 | 350 | ||
344 | // If the physics engine runs on its own thread, start same. | 351 | // If the physics engine runs on its own thread, start same. |
345 | if (BSParam.UseSeparatePhysicsThread) | 352 | if (BSParam.UseSeparatePhysicsThread) |
346 | { | 353 | { |
347 | // The physics simulation should happen independently of the heartbeat loop | 354 | // The physics simulation should happen independently of the heartbeat loop |
348 | m_physicsThread | 355 | m_physicsThread |
349 | = WorkManager.StartThread( | 356 | = WorkManager.StartThread( |
350 | BulletSPluginPhysicsThread, | 357 | BulletSPluginPhysicsThread, |
351 | string.Format("{0} ({1})", BulletEngineName, RegionName), | 358 | string.Format("{0} ({1})", BulletEngineName, RegionName), |
352 | ThreadPriority.Normal, | 359 | ThreadPriority.Normal, |
353 | true, | 360 | true, |
354 | true); | 361 | true); |
355 | } | 362 | } |
356 | } | 363 | } |
@@ -523,13 +530,13 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
523 | return null; | 530 | return null; |
524 | } | 531 | } |
525 | 532 | ||
526 | public override PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 velocity, Vector3 size, bool isFlying) | 533 | public override PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, float footOffset, bool isFlying) |
527 | { | 534 | { |
528 | // m_log.DebugFormat("{0}: AddAvatar: {1}", LogHeader, avName); | 535 | // m_log.DebugFormat("{0}: AddAvatar: {1}", LogHeader, avName); |
529 | 536 | ||
530 | if (!m_initialized) return null; | 537 | if (!m_initialized) return null; |
531 | 538 | ||
532 | BSCharacter actor = new BSCharacter(localID, avName, this, position, velocity, size, isFlying); | 539 | BSCharacter actor = new BSCharacter(localID, avName, this, position, Vector3.Zero, size, footOffset, isFlying); |
533 | lock (PhysObjects) | 540 | lock (PhysObjects) |
534 | PhysObjects.Add(localID, actor); | 541 | PhysObjects.Add(localID, actor); |
535 | 542 | ||
@@ -651,49 +658,57 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
651 | 658 | ||
652 | int beforeTime = Util.EnvironmentTickCount(); | 659 | int beforeTime = Util.EnvironmentTickCount(); |
653 | int simTime = 0; | 660 | int simTime = 0; |
661 | int numTaints = 0; | ||
662 | int numSubSteps = 0; | ||
654 | 663 | ||
655 | int numTaints = _taintOperations.Count; | 664 | lock (PhysicsEngineLock) |
656 | 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(); | ||
657 | 669 | ||
658 | // update the prim states while we know the physics engine is not busy | 670 | // Some of the physical objects requre individual, pre-step calls |
659 | ProcessTaints(); | 671 | // (vehicles and avatar movement, in particular) |
672 | TriggerPreStepEvent(timeStep); | ||
660 | 673 | ||
661 | // Some of the physical objects requre individual, pre-step calls | 674 | // the prestep actions might have added taints |
662 | // (vehicles and avatar movement, in particular) | 675 | numTaints += ProcessTaints(); |
663 | TriggerPreStepEvent(timeStep); | ||
664 | 676 | ||
665 | // 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. |
666 | numTaints += _taintOperations.Count; | 678 | // Only enable this in a limited test world with few objects. |
667 | ProcessTaints(); | 679 | if (m_physicsPhysicalDumpEnabled) |
680 | PE.DumpAllInfo(World); | ||
668 | 681 | ||
669 | 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 | } | ||
670 | 697 | ||
671 | // 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 |
672 | // Only enable this in a limited test world with few objects. | 699 | if (PhysicsMetricDumpFrames != 0 && ((m_simulationStep % PhysicsMetricDumpFrames) == 0)) |
673 | if (m_physicsPhysicalDumpEnabled) | 700 | PE.DumpPhysicsStatistics(World); |
674 | PE.DumpAllInfo(World); | ||
675 | 701 | ||
676 | // step the physical world one interval | 702 | InSimulationTime = false; |
677 | m_simulationStep++; | ||
678 | int numSubSteps = 0; | ||
679 | try | ||
680 | { | ||
681 | numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount); | ||
682 | 703 | ||
683 | } | 704 | // Some actors want to know when the simulation step is complete. |
684 | catch (Exception e) | 705 | TriggerPostStepEvent(timeStep); |
685 | { | 706 | |
686 | m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}", | 707 | // In case there were any parameter updates that happened during the simulation step |
687 | LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e); | 708 | numTaints += ProcessTaints(); |
688 | DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}", | ||
689 | DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); | ||
690 | updatedEntityCount = 0; | ||
691 | collidersCount = 0; | ||
692 | } | ||
693 | 709 | ||
694 | // Make the physics engine dump useful statistics periodically | 710 | InSimulationTime = false; |
695 | if (PhysicsMetricDumpFrames != 0 && ((m_simulationStep % PhysicsMetricDumpFrames) == 0)) | 711 | } |
696 | PE.DumpPhysicsStatistics(World); | ||
697 | 712 | ||
698 | // 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. |
699 | SimulationNowTime = Util.EnvironmentTickCount(); | 714 | SimulationNowTime = Util.EnvironmentTickCount(); |
@@ -743,9 +758,6 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
743 | } | 758 | } |
744 | } | 759 | } |
745 | 760 | ||
746 | // Some actors want to know when the simulation step is complete. | ||
747 | TriggerPostStepEvent(timeStep); | ||
748 | |||
749 | simTime = Util.EnvironmentTickCountSubtract(beforeTime); | 761 | simTime = Util.EnvironmentTickCountSubtract(beforeTime); |
750 | if (PhysicsLogging.Enabled) | 762 | if (PhysicsLogging.Enabled) |
751 | { | 763 | { |
@@ -762,7 +774,8 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
762 | // The physics engine returns the number of milliseconds it simulated this call. | 774 | // The physics engine returns the number of milliseconds it simulated this call. |
763 | // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. | 775 | // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. |
764 | // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55). | 776 | // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55). |
765 | m_simulatedTime += (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate; | 777 | // m_simulatedTime += (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate; |
778 | m_simulatedTime += (float)numSubSteps * m_fixedTimeStep; | ||
766 | } | 779 | } |
767 | 780 | ||
768 | // Called by a BSPhysObject to note that it has changed properties and this information | 781 | // Called by a BSPhysObject to note that it has changed properties and this information |
@@ -849,7 +862,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
849 | 862 | ||
850 | // Return the framerate simulated to give the above returned results. | 863 | // Return the framerate simulated to give the above returned results. |
851 | // (Race condition here but this is just bookkeeping so rare mistakes do not merit a lock). | 864 | // (Race condition here but this is just bookkeeping so rare mistakes do not merit a lock). |
852 | float simTime = m_simulatedTime; | 865 | float simTime = m_simulatedTime / timeStep; |
853 | m_simulatedTime = 0f; | 866 | m_simulatedTime = 0f; |
854 | return simTime; | 867 | return simTime; |
855 | } | 868 | } |
@@ -879,7 +892,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
879 | 892 | ||
880 | if (collider.IsInitialized) | 893 | if (collider.IsInitialized) |
881 | { | 894 | { |
882 | if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) | 895 | if (collider.Collide(collidee, collidePoint, collideNormal, penetration)) |
883 | { | 896 | { |
884 | // If a collision was 'good', remember to send it to the simulator | 897 | // If a collision was 'good', remember to send it to the simulator |
885 | lock (CollisionLock) | 898 | lock (CollisionLock) |
@@ -948,26 +961,150 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
948 | // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); | 961 | // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); |
949 | } | 962 | } |
950 | 963 | ||
951 | // Although no one seems to check this, I do support combining. | 964 | #endregion // Terrain |
952 | public override bool SupportsCombining() | 965 | |
966 | #region Raycast | ||
967 | |||
968 | public override bool SupportsRayCast() | ||
953 | { | 969 | { |
954 | return TerrainManager.SupportsCombining(); | 970 | return BSParam.UseBulletRaycast; |
955 | } | 971 | } |
956 | // This call says I am a child to region zero in a mega-region. 'pScene' is that | 972 | |
957 | // of region zero, 'offset' is my offset from regions zero's origin, and | 973 | public override bool SupportsRaycastWorldFiltered() |
958 | // 'extents' is the largest XY that is handled in my region. | ||
959 | public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) | ||
960 | { | 974 | { |
961 | TerrainManager.Combine(pScene, offset, extents); | 975 | return BSParam.UseBulletRaycast; |
962 | } | 976 | } |
963 | 977 | ||
964 | // Unhook all the combining that I know about. | 978 | |
965 | public override void UnCombine(PhysicsScene pScene) | 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) | ||
966 | { | 1000 | { |
967 | TerrainManager.UnCombine(pScene); | 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 | } | ||
968 | } | 1019 | } |
969 | 1020 | ||
970 | #endregion // Terrain | 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 | |||
971 | 1108 | ||
972 | public override Dictionary<uint, float> GetTopColliders() | 1109 | public override Dictionary<uint, float> GetTopColliders() |
973 | { | 1110 | { |
@@ -1081,32 +1218,35 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
1081 | // 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 |
1082 | // 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. |
1083 | // 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. |
1084 | 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) | ||
1085 | { | 1228 | { |
1086 | TaintedObject(false /*inTaintTime*/, pOriginator, pIdent, pCallback); | 1229 | TaintedObject(m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback); |
1087 | } | 1230 | } |
1088 | public void TaintedObject(uint pOriginator, String pIdent, TaintCallback pCallback) | 1231 | public void TaintedObject(uint pOriginator, String pIdent, TaintCallback pCallback) |
1089 | { | 1232 | { |
1090 | TaintedObject(false /*inTaintTime*/, m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback); | 1233 | TaintedObject(m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback); |
1091 | } | ||
1092 | public void TaintedObject(bool inTaintTime, String pIdent, TaintCallback pCallback) | ||
1093 | { | ||
1094 | TaintedObject(inTaintTime, BSScene.DetailLogZero, pIdent, pCallback); | ||
1095 | } | ||
1096 | public void TaintedObject(bool inTaintTime, uint pOriginator, String pIdent, TaintCallback pCallback) | ||
1097 | { | ||
1098 | TaintedObject(inTaintTime, m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback); | ||
1099 | } | 1234 | } |
1100 | // 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. |
1101 | // 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. |
1102 | public void TaintedObject(bool inTaintTime, string pOriginator, string pIdent, TaintCallback pCallback) | 1237 | public void TaintedObject(string pOriginator, string pIdent, TaintCallback pCallback) |
1103 | { | 1238 | { |
1104 | if (!m_initialized) return; | 1239 | if (!m_initialized) return; |
1105 | 1240 | ||
1106 | if (inTaintTime) | 1241 | if (Monitor.TryEnter(PhysicsEngineLock)) |
1242 | { | ||
1243 | // If we can get exclusive access to the physics engine, just do the operation | ||
1107 | pCallback(); | 1244 | pCallback(); |
1245 | Monitor.Exit(PhysicsEngineLock); | ||
1246 | } | ||
1108 | else | 1247 | else |
1109 | { | 1248 | { |
1249 | // The physics engine is busy, queue the operation | ||
1110 | lock (_taintLock) | 1250 | lock (_taintLock) |
1111 | { | 1251 | { |
1112 | _taintOperations.Add(new TaintCallbackEntry(pOriginator, pIdent, pCallback)); | 1252 | _taintOperations.Add(new TaintCallbackEntry(pOriginator, pIdent, pCallback)); |
@@ -1133,14 +1273,21 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
1133 | // 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 |
1134 | // 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 |
1135 | // 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. |
1136 | public void ProcessTaints() | 1276 | // Returns the number of taints processed |
1277 | // NOTE: Called while PhysicsEngineLock is locked | ||
1278 | public int ProcessTaints() | ||
1137 | { | 1279 | { |
1138 | ProcessRegularTaints(); | 1280 | int ret = 0; |
1139 | ProcessPostTaintTaints(); | 1281 | ret += ProcessRegularTaints(); |
1282 | ret += ProcessPostTaintTaints(); | ||
1283 | return ret; | ||
1140 | } | 1284 | } |
1141 | 1285 | ||
1142 | private void ProcessRegularTaints() | 1286 | // Returns the number of taints processed |
1287 | // NOTE: Called while PhysicsEngineLock is locked | ||
1288 | private int ProcessRegularTaints() | ||
1143 | { | 1289 | { |
1290 | int ret = 0; | ||
1144 | 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 |
1145 | { | 1292 | { |
1146 | // 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 |
@@ -1157,6 +1304,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
1157 | { | 1304 | { |
1158 | 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 |
1159 | tcbe.callback(); | 1306 | tcbe.callback(); |
1307 | ret++; | ||
1160 | } | 1308 | } |
1161 | catch (Exception e) | 1309 | catch (Exception e) |
1162 | { | 1310 | { |
@@ -1165,6 +1313,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
1165 | } | 1313 | } |
1166 | oldList.Clear(); | 1314 | oldList.Clear(); |
1167 | } | 1315 | } |
1316 | return ret; | ||
1168 | } | 1317 | } |
1169 | 1318 | ||
1170 | // 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. |
@@ -1183,8 +1332,11 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
1183 | } | 1332 | } |
1184 | 1333 | ||
1185 | // 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. |
1186 | private void ProcessPostTaintTaints() | 1335 | // Returns the number of taints processed |
1336 | // NOTE: Called while PhysicsEngineLock is locked | ||
1337 | private int ProcessPostTaintTaints() | ||
1187 | { | 1338 | { |
1339 | int ret = 0; | ||
1188 | if (m_initialized && _postTaintOperations.Count > 0) | 1340 | if (m_initialized && _postTaintOperations.Count > 0) |
1189 | { | 1341 | { |
1190 | Dictionary<string, TaintCallbackEntry> oldList; | 1342 | Dictionary<string, TaintCallbackEntry> oldList; |
@@ -1200,6 +1352,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
1200 | { | 1352 | { |
1201 | 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 |
1202 | kvp.Value.callback(); | 1354 | kvp.Value.callback(); |
1355 | ret++; | ||
1203 | } | 1356 | } |
1204 | catch (Exception e) | 1357 | catch (Exception e) |
1205 | { | 1358 | { |
@@ -1208,20 +1361,8 @@ namespace OpenSim.Region.PhysicsModule.BulletS | |||
1208 | } | 1361 | } |
1209 | oldList.Clear(); | 1362 | oldList.Clear(); |
1210 | } | 1363 | } |
1364 | return ret; | ||
1211 | } | 1365 | } |
1212 | |||
1213 | // Only used for debugging. Does not change state of anything so locking is not necessary. | ||
1214 | public bool AssertInTaintTime(string whereFrom) | ||
1215 | { | ||
1216 | if (!InTaintTime) | ||
1217 | { | ||
1218 | DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); | ||
1219 | m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); | ||
1220 | // Util.PrintCallStack(DetailLog); | ||
1221 | } | ||
1222 | return InTaintTime; | ||
1223 | } | ||
1224 | |||
1225 | #endregion // Taints | 1366 | #endregion // Taints |
1226 | 1367 | ||
1227 | #region IPhysicsParameters | 1368 | #region IPhysicsParameters |