diff options
9 files changed, 268 insertions, 29 deletions
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs index cdd7cc7..8ac9090 100644 --- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs | |||
@@ -355,10 +355,19 @@ Asset service request failures: {3}" + Environment.NewLine, | |||
355 | sb.Append(Environment.NewLine); | 355 | sb.Append(Environment.NewLine); |
356 | sb.Append( | 356 | sb.Append( |
357 | string.Format( | 357 | string.Format( |
358 | "{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}", | 358 | "{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}\n\n", |
359 | inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, | 359 | inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, |
360 | netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); | 360 | netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); |
361 | sb.Append(Environment.NewLine); | 361 | |
362 | foreach (KeyValuePair<string, Stat> kvp in StatsManager.RegisteredStats) | ||
363 | { | ||
364 | Stat stat = kvp.Value; | ||
365 | |||
366 | if (stat.Category == "scene" && stat.Verbosity == StatVerbosity.Info) | ||
367 | { | ||
368 | sb.AppendFormat("Slow frames ({0}): {1}\n", stat.Container, stat.Value); | ||
369 | } | ||
370 | } | ||
362 | 371 | ||
363 | /* | 372 | /* |
364 | sb.Append(Environment.NewLine); | 373 | sb.Append(Environment.NewLine); |
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs index d78fa6a..b5dc24f 100644 --- a/OpenSim/Framework/Monitoring/StatsManager.cs +++ b/OpenSim/Framework/Monitoring/StatsManager.cs | |||
@@ -25,6 +25,9 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | |||
28 | namespace OpenSim.Framework.Monitoring | 31 | namespace OpenSim.Framework.Monitoring |
29 | { | 32 | { |
30 | /// <summary> | 33 | /// <summary> |
@@ -32,6 +35,14 @@ namespace OpenSim.Framework.Monitoring | |||
32 | /// </summary> | 35 | /// </summary> |
33 | public class StatsManager | 36 | public class StatsManager |
34 | { | 37 | { |
38 | /// <summary> | ||
39 | /// Registered stats. | ||
40 | /// </summary> | ||
41 | /// <remarks> | ||
42 | /// Do not add or remove from this dictionary. | ||
43 | /// </remarks> | ||
44 | public static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>(); | ||
45 | |||
35 | private static AssetStatsCollector assetStats; | 46 | private static AssetStatsCollector assetStats; |
36 | private static UserStatsCollector userStats; | 47 | private static UserStatsCollector userStats; |
37 | private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); | 48 | private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); |
@@ -61,5 +72,139 @@ namespace OpenSim.Framework.Monitoring | |||
61 | 72 | ||
62 | return userStats; | 73 | return userStats; |
63 | } | 74 | } |
75 | |||
76 | public static bool RegisterStat(Stat stat) | ||
77 | { | ||
78 | lock (RegisteredStats) | ||
79 | { | ||
80 | if (RegisteredStats.ContainsKey(stat.UniqueName)) | ||
81 | { | ||
82 | // XXX: For now just return false. This is to avoid problems in regression tests where all tests | ||
83 | // in a class are run in the same instance of the VM. | ||
84 | return false; | ||
85 | |||
86 | // throw new Exception( | ||
87 | // "StatsManager already contains stat with ShortName {0} in Category {1}", stat.ShortName, stat.Category); | ||
88 | } | ||
89 | |||
90 | // We take a replace-on-write approach here so that we don't need to generate a new Dictionary | ||
91 | Dictionary<string, Stat> newRegisteredStats = new Dictionary<string, Stat>(RegisteredStats); | ||
92 | newRegisteredStats[stat.UniqueName] = stat; | ||
93 | RegisteredStats = newRegisteredStats; | ||
94 | } | ||
95 | |||
96 | return true; | ||
97 | } | ||
98 | |||
99 | public static bool DeregisterStat(Stat stat) | ||
100 | { | ||
101 | lock (RegisteredStats) | ||
102 | { | ||
103 | if (!RegisteredStats.ContainsKey(stat.UniqueName)) | ||
104 | return false; | ||
105 | |||
106 | Dictionary<string, Stat> newRegisteredStats = new Dictionary<string, Stat>(RegisteredStats); | ||
107 | newRegisteredStats.Remove(stat.UniqueName); | ||
108 | RegisteredStats = newRegisteredStats; | ||
109 | |||
110 | return true; | ||
111 | } | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /// <summary> | ||
116 | /// Verbosity of stat. | ||
117 | /// </summary> | ||
118 | /// <remarks> | ||
119 | /// Info will always be displayed. | ||
120 | /// </remarks> | ||
121 | public enum StatVerbosity | ||
122 | { | ||
123 | Debug, | ||
124 | Info | ||
125 | } | ||
126 | |||
127 | /// <summary> | ||
128 | /// Holds individual static details | ||
129 | /// </summary> | ||
130 | public class Stat | ||
131 | { | ||
132 | /// <summary> | ||
133 | /// Unique stat name used for indexing. Each ShortName in a Category must be unique. | ||
134 | /// </summary> | ||
135 | public string UniqueName { get; private set; } | ||
136 | |||
137 | /// <summary> | ||
138 | /// Category of this stat (e.g. cache, scene, etc). | ||
139 | /// </summary> | ||
140 | public string Category { get; private set; } | ||
141 | |||
142 | /// <summary> | ||
143 | /// Containing name for this stat. | ||
144 | /// FIXME: In the case of a scene, this is currently the scene name (though this leaves | ||
145 | /// us with a to-be-resolved problem of non-unique region names). | ||
146 | /// </summary> | ||
147 | /// <value> | ||
148 | /// The container. | ||
149 | /// </value> | ||
150 | public string Container { get; private set; } | ||
151 | |||
152 | public StatVerbosity Verbosity { get; private set; } | ||
153 | public string ShortName { get; private set; } | ||
154 | public string Name { get; private set; } | ||
155 | public string Description { get; private set; } | ||
156 | public virtual string UnitName { get; private set; } | ||
157 | |||
158 | public virtual double Value { get; set; } | ||
159 | |||
160 | public Stat( | ||
161 | string shortName, string name, string unitName, string category, string container, StatVerbosity verbosity, string description) | ||
162 | { | ||
163 | ShortName = shortName; | ||
164 | Name = name; | ||
165 | UnitName = unitName; | ||
166 | Category = category; | ||
167 | Container = container; | ||
168 | Verbosity = verbosity; | ||
169 | Description = description; | ||
170 | |||
171 | UniqueName = GenUniqueName(Container, Category, ShortName); | ||
172 | } | ||
173 | |||
174 | public static string GenUniqueName(string container, string category, string shortName) | ||
175 | { | ||
176 | return string.Format("{0}+{1}+{2}", container, category, shortName); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | public class PercentageStat : Stat | ||
181 | { | ||
182 | public int Antecedent { get; set; } | ||
183 | public int Consequent { get; set; } | ||
184 | |||
185 | public override double Value | ||
186 | { | ||
187 | get | ||
188 | { | ||
189 | int c = Consequent; | ||
190 | |||
191 | // Avoid any chance of a multi-threaded divide-by-zero | ||
192 | if (c == 0) | ||
193 | return 0; | ||
194 | |||
195 | return (double)Antecedent / c; | ||
196 | } | ||
197 | |||
198 | set | ||
199 | { | ||
200 | throw new Exception("Cannot set value on a PercentageStat"); | ||
201 | } | ||
202 | } | ||
203 | |||
204 | public PercentageStat( | ||
205 | string shortName, string name, string category, string container, StatVerbosity verbosity, string description) | ||
206 | : base(shortName, name, " %", category, container, verbosity, description) | ||
207 | { | ||
208 | } | ||
64 | } | 209 | } |
65 | } \ No newline at end of file | 210 | } \ No newline at end of file |
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index bd7bd82..e3bf997 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | |||
@@ -525,7 +525,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
525 | { | 525 | { |
526 | for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) | 526 | for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) |
527 | { | 527 | { |
528 | for (int j = 0; j < appearance.Wearables[j].Count; j++) | 528 | for (int j = 0; j < appearance.Wearables[i].Count; j++) |
529 | { | 529 | { |
530 | if (appearance.Wearables[i][j].ItemID == UUID.Zero) | 530 | if (appearance.Wearables[i][j].ItemID == UUID.Zero) |
531 | continue; | 531 | continue; |
@@ -533,6 +533,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
533 | // Ignore ruth's assets | 533 | // Ignore ruth's assets |
534 | if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) | 534 | if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) |
535 | continue; | 535 | continue; |
536 | |||
536 | InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); | 537 | InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); |
537 | baseItem = invService.GetItem(baseItem); | 538 | baseItem = invService.GetItem(baseItem); |
538 | 539 | ||
diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs index e135c21..e411585 100644 --- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs | |||
@@ -95,14 +95,14 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
95 | { | 95 | { |
96 | foreach (IMonitor monitor in m_staticMonitors) | 96 | foreach (IMonitor monitor in m_staticMonitors) |
97 | { | 97 | { |
98 | m_log.InfoFormat( | 98 | MainConsole.Instance.OutputFormat( |
99 | "[MONITOR MODULE]: {0} reports {1} = {2}", | 99 | "[MONITOR MODULE]: {0} reports {1} = {2}", |
100 | m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue()); | 100 | m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue()); |
101 | } | 101 | } |
102 | 102 | ||
103 | foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats()) | 103 | foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats()) |
104 | { | 104 | { |
105 | m_log.InfoFormat( | 105 | MainConsole.Instance.OutputFormat( |
106 | "[MONITOR MODULE]: {0} reports {1} = {2}", | 106 | "[MONITOR MODULE]: {0} reports {1} = {2}", |
107 | m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value); | 107 | m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value); |
108 | } | 108 | } |
diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs index 33041e9..ad421ee 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs | |||
@@ -87,7 +87,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
87 | { | 87 | { |
88 | if (m_defaultAnimation.AnimID == animID) | 88 | if (m_defaultAnimation.AnimID == animID) |
89 | { | 89 | { |
90 | ResetDefaultAnimation(); | 90 | m_defaultAnimation = new OpenSim.Framework.Animation(UUID.Zero, 1, UUID.Zero); |
91 | } | 91 | } |
92 | else if (HasAnimation(animID)) | 92 | else if (HasAnimation(animID)) |
93 | { | 93 | { |
@@ -149,19 +149,26 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
149 | { | 149 | { |
150 | lock (m_animations) | 150 | lock (m_animations) |
151 | { | 151 | { |
152 | animIDs = new UUID[m_animations.Count + 1]; | 152 | int defaultSize = 0; |
153 | sequenceNums = new int[m_animations.Count + 1]; | 153 | if (m_defaultAnimation.AnimID != UUID.Zero) |
154 | objectIDs = new UUID[m_animations.Count + 1]; | 154 | defaultSize++; |
155 | 155 | ||
156 | animIDs[0] = m_defaultAnimation.AnimID; | 156 | animIDs = new UUID[m_animations.Count + defaultSize]; |
157 | sequenceNums[0] = m_defaultAnimation.SequenceNum; | 157 | sequenceNums = new int[m_animations.Count + defaultSize]; |
158 | objectIDs[0] = m_defaultAnimation.ObjectID; | 158 | objectIDs = new UUID[m_animations.Count + defaultSize]; |
159 | |||
160 | if (m_defaultAnimation.AnimID != UUID.Zero) | ||
161 | { | ||
162 | animIDs[0] = m_defaultAnimation.AnimID; | ||
163 | sequenceNums[0] = m_defaultAnimation.SequenceNum; | ||
164 | objectIDs[0] = m_defaultAnimation.ObjectID; | ||
165 | } | ||
159 | 166 | ||
160 | for (int i = 0; i < m_animations.Count; ++i) | 167 | for (int i = 0; i < m_animations.Count; ++i) |
161 | { | 168 | { |
162 | animIDs[i + 1] = m_animations[i].AnimID; | 169 | animIDs[i + defaultSize] = m_animations[i].AnimID; |
163 | sequenceNums[i + 1] = m_animations[i].SequenceNum; | 170 | sequenceNums[i + defaultSize] = m_animations[i].SequenceNum; |
164 | objectIDs[i + 1] = m_animations[i].ObjectID; | 171 | objectIDs[i + defaultSize] = m_animations[i].ObjectID; |
165 | } | 172 | } |
166 | } | 173 | } |
167 | } | 174 | } |
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 50a176b..9458079 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs | |||
@@ -424,13 +424,19 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
424 | { | 424 | { |
425 | lock (m_animations) | 425 | lock (m_animations) |
426 | { | 426 | { |
427 | CurrentMovementAnimation = DetermineMovementAnimation(); | 427 | string newMovementAnimation = DetermineMovementAnimation(); |
428 | if (CurrentMovementAnimation != newMovementAnimation) | ||
429 | { | ||
430 | CurrentMovementAnimation = DetermineMovementAnimation(); | ||
428 | 431 | ||
429 | // m_log.DebugFormat( | 432 | // m_log.DebugFormat( |
430 | // "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()", | 433 | // "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()", |
431 | // CurrentMovementAnimation, m_scenePresence.Name); | 434 | // CurrentMovementAnimation, m_scenePresence.Name); |
432 | 435 | ||
433 | TrySetMovementAnimation(CurrentMovementAnimation); | 436 | // Only set it if it's actually changed, give a script |
437 | // a chance to stop a default animation | ||
438 | TrySetMovementAnimation(CurrentMovementAnimation); | ||
439 | } | ||
434 | } | 440 | } |
435 | } | 441 | } |
436 | 442 | ||
@@ -552,4 +558,4 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
552 | SendAnimPack(animIDs, sequenceNums, objectIDs); | 558 | SendAnimPack(animIDs, sequenceNums, objectIDs); |
553 | } | 559 | } |
554 | } | 560 | } |
555 | } \ No newline at end of file | 561 | } |
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index 756b1f4..0d359b9 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs | |||
@@ -47,6 +47,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
47 | = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 47 | = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
48 | 48 | ||
49 | public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates"; | 49 | public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates"; |
50 | public const string SlowFramesStatName = "SlowFrames"; | ||
50 | 51 | ||
51 | public delegate void SendStatResult(SimStats stats); | 52 | public delegate void SendStatResult(SimStats stats); |
52 | 53 | ||
@@ -129,6 +130,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
129 | } | 130 | } |
130 | 131 | ||
131 | /// <summary> | 132 | /// <summary> |
133 | /// Number of frames that have taken longer to process than Scene.MIN_FRAME_TIME | ||
134 | /// </summary> | ||
135 | public Stat SlowFramesStat { get; private set; } | ||
136 | |||
137 | /// <summary> | ||
138 | /// The threshold at which we log a slow frame. | ||
139 | /// </summary> | ||
140 | public int SlowFramesStatReportThreshold { get; private set; } | ||
141 | |||
142 | /// <summary> | ||
132 | /// Extra sim statistics that are used by monitors but not sent to the client. | 143 | /// Extra sim statistics that are used by monitors but not sent to the client. |
133 | /// </summary> | 144 | /// </summary> |
134 | /// <value> | 145 | /// <value> |
@@ -226,6 +237,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
226 | 237 | ||
227 | if (StatsManager.SimExtraStats != null) | 238 | if (StatsManager.SimExtraStats != null) |
228 | OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; | 239 | OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; |
240 | |||
241 | /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit | ||
242 | /// longer than ideal (which in itself is a concern). | ||
243 | SlowFramesStatReportThreshold = (int)Math.Ceiling(m_scene.MinFrameTime * 1000 * 1.2); | ||
244 | |||
245 | SlowFramesStat | ||
246 | = new Stat( | ||
247 | "SlowFrames", | ||
248 | "Slow Frames", | ||
249 | " frames", | ||
250 | "scene", | ||
251 | m_scene.Name, | ||
252 | StatVerbosity.Info, | ||
253 | "Number of frames where frame time has been significantly longer than the desired frame time."); | ||
254 | |||
255 | StatsManager.RegisterStat(SlowFramesStat); | ||
229 | } | 256 | } |
230 | 257 | ||
231 | public void Close() | 258 | public void Close() |
@@ -443,6 +470,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
443 | lock (m_lastReportedExtraSimStats) | 470 | lock (m_lastReportedExtraSimStats) |
444 | { | 471 | { |
445 | m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; | 472 | m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; |
473 | m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value; | ||
446 | 474 | ||
447 | Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats(); | 475 | Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats(); |
448 | 476 | ||
@@ -563,6 +591,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
563 | public void addFrameMS(int ms) | 591 | public void addFrameMS(int ms) |
564 | { | 592 | { |
565 | m_frameMS += ms; | 593 | m_frameMS += ms; |
594 | |||
595 | // At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit | ||
596 | // longer than ideal due to the inaccuracy of the Sleep in Scene.Update() (which in itself is a concern). | ||
597 | if (ms > SlowFramesStatReportThreshold) | ||
598 | SlowFramesStat.Value++; | ||
566 | } | 599 | } |
567 | 600 | ||
568 | public void addNetMS(int ms) | 601 | public void addNetMS(int ms) |
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 6efa4d1..eb02536 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | |||
@@ -63,6 +63,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
63 | 63 | ||
64 | private bool m_isphysical; | 64 | private bool m_isphysical; |
65 | 65 | ||
66 | public int ExpectedCollisionContacts { get { return m_expectedCollisionContacts; } } | ||
67 | private int m_expectedCollisionContacts = 0; | ||
68 | |||
66 | /// <summary> | 69 | /// <summary> |
67 | /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. | 70 | /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. |
68 | /// </summary> | 71 | /// </summary> |
@@ -150,7 +153,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
150 | 153 | ||
151 | private PrimitiveBaseShape _pbs; | 154 | private PrimitiveBaseShape _pbs; |
152 | private OdeScene _parent_scene; | 155 | private OdeScene _parent_scene; |
153 | 156 | ||
154 | /// <summary> | 157 | /// <summary> |
155 | /// The physics space which contains prim geometries | 158 | /// The physics space which contains prim geometries |
156 | /// </summary> | 159 | /// </summary> |
@@ -840,7 +843,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
840 | int vertexStride, triStride; | 843 | int vertexStride, triStride; |
841 | mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap | 844 | mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap |
842 | mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage | 845 | mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage |
843 | 846 | m_expectedCollisionContacts = indexCount; | |
844 | mesh.releaseSourceMeshData(); // free up the original mesh data to save memory | 847 | mesh.releaseSourceMeshData(); // free up the original mesh data to save memory |
845 | 848 | ||
846 | // We must lock here since m_MeshToTriMeshMap is static and multiple scene threads may call this method at | 849 | // We must lock here since m_MeshToTriMeshMap is static and multiple scene threads may call this method at |
@@ -1377,6 +1380,7 @@ Console.WriteLine("CreateGeom:"); | |||
1377 | { | 1380 | { |
1378 | //Console.WriteLine(" CreateGeom 1"); | 1381 | //Console.WriteLine(" CreateGeom 1"); |
1379 | SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); | 1382 | SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); |
1383 | m_expectedCollisionContacts = 3; | ||
1380 | } | 1384 | } |
1381 | catch (AccessViolationException) | 1385 | catch (AccessViolationException) |
1382 | { | 1386 | { |
@@ -1391,6 +1395,7 @@ Console.WriteLine("CreateGeom:"); | |||
1391 | { | 1395 | { |
1392 | //Console.WriteLine(" CreateGeom 2"); | 1396 | //Console.WriteLine(" CreateGeom 2"); |
1393 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | 1397 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); |
1398 | m_expectedCollisionContacts = 4; | ||
1394 | } | 1399 | } |
1395 | catch (AccessViolationException) | 1400 | catch (AccessViolationException) |
1396 | { | 1401 | { |
@@ -1406,6 +1411,7 @@ Console.WriteLine("CreateGeom:"); | |||
1406 | { | 1411 | { |
1407 | //Console.WriteLine(" CreateGeom 3"); | 1412 | //Console.WriteLine(" CreateGeom 3"); |
1408 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | 1413 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); |
1414 | m_expectedCollisionContacts = 4; | ||
1409 | } | 1415 | } |
1410 | catch (AccessViolationException) | 1416 | catch (AccessViolationException) |
1411 | { | 1417 | { |
@@ -1421,6 +1427,7 @@ Console.WriteLine("CreateGeom:"); | |||
1421 | { | 1427 | { |
1422 | //Console.WriteLine(" CreateGeom 4"); | 1428 | //Console.WriteLine(" CreateGeom 4"); |
1423 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | 1429 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); |
1430 | m_expectedCollisionContacts = 4; | ||
1424 | } | 1431 | } |
1425 | catch (AccessViolationException) | 1432 | catch (AccessViolationException) |
1426 | { | 1433 | { |
@@ -1446,11 +1453,13 @@ Console.WriteLine("CreateGeom:"); | |||
1446 | _parent_scene.geom_name_map.Remove(prim_geom); | 1453 | _parent_scene.geom_name_map.Remove(prim_geom); |
1447 | _parent_scene.actor_name_map.Remove(prim_geom); | 1454 | _parent_scene.actor_name_map.Remove(prim_geom); |
1448 | d.GeomDestroy(prim_geom); | 1455 | d.GeomDestroy(prim_geom); |
1456 | m_expectedCollisionContacts = 0; | ||
1449 | prim_geom = IntPtr.Zero; | 1457 | prim_geom = IntPtr.Zero; |
1450 | } | 1458 | } |
1451 | catch (System.AccessViolationException) | 1459 | catch (System.AccessViolationException) |
1452 | { | 1460 | { |
1453 | prim_geom = IntPtr.Zero; | 1461 | prim_geom = IntPtr.Zero; |
1462 | m_expectedCollisionContacts = 0; | ||
1454 | m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name); | 1463 | m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name); |
1455 | 1464 | ||
1456 | return false; | 1465 | return false; |
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 929b019..7a50c4c 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs | |||
@@ -336,6 +336,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
336 | 336 | ||
337 | public int geomContactPointsStartthrottle = 3; | 337 | public int geomContactPointsStartthrottle = 3; |
338 | public int geomUpdatesPerThrottledUpdate = 15; | 338 | public int geomUpdatesPerThrottledUpdate = 15; |
339 | private const int avatarExpectedContacts = 3; | ||
339 | 340 | ||
340 | public float bodyPIDD = 35f; | 341 | public float bodyPIDD = 35f; |
341 | public float bodyPIDG = 25; | 342 | public float bodyPIDG = 25; |
@@ -474,6 +475,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
474 | private OdePrim cp1; | 475 | private OdePrim cp1; |
475 | private OdeCharacter cc2; | 476 | private OdeCharacter cc2; |
476 | private OdePrim cp2; | 477 | private OdePrim cp2; |
478 | private int p1ExpectedPoints = 0; | ||
479 | private int p2ExpectedPoints = 0; | ||
477 | //private int cStartStop = 0; | 480 | //private int cStartStop = 0; |
478 | //private string cDictKey = ""; | 481 | //private string cDictKey = ""; |
479 | 482 | ||
@@ -498,6 +501,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
498 | public int physics_logging_interval = 0; | 501 | public int physics_logging_interval = 0; |
499 | public bool physics_logging_append_existing_logfile = false; | 502 | public bool physics_logging_append_existing_logfile = false; |
500 | 503 | ||
504 | |||
501 | public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); | 505 | public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); |
502 | public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); | 506 | public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); |
503 | 507 | ||
@@ -644,7 +648,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
644 | 648 | ||
645 | contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); | 649 | contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); |
646 | 650 | ||
647 | geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3); | 651 | geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 5); |
648 | geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15); | 652 | geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15); |
649 | geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5); | 653 | geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5); |
650 | 654 | ||
@@ -1064,7 +1068,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1064 | 1068 | ||
1065 | PhysicsActor p1; | 1069 | PhysicsActor p1; |
1066 | PhysicsActor p2; | 1070 | PhysicsActor p2; |
1067 | 1071 | ||
1072 | p1ExpectedPoints = 0; | ||
1073 | p2ExpectedPoints = 0; | ||
1074 | |||
1068 | if (!actor_name_map.TryGetValue(g1, out p1)) | 1075 | if (!actor_name_map.TryGetValue(g1, out p1)) |
1069 | { | 1076 | { |
1070 | p1 = PANull; | 1077 | p1 = PANull; |
@@ -1121,9 +1128,13 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1121 | switch (p1.PhysicsActorType) | 1128 | switch (p1.PhysicsActorType) |
1122 | { | 1129 | { |
1123 | case (int)ActorTypes.Agent: | 1130 | case (int)ActorTypes.Agent: |
1131 | p1ExpectedPoints = avatarExpectedContacts; | ||
1124 | p2.CollidingObj = true; | 1132 | p2.CollidingObj = true; |
1125 | break; | 1133 | break; |
1126 | case (int)ActorTypes.Prim: | 1134 | case (int)ActorTypes.Prim: |
1135 | if (p1 != null && p1 is OdePrim) | ||
1136 | p1ExpectedPoints = ((OdePrim) p1).ExpectedCollisionContacts; | ||
1137 | |||
1127 | if (p2.Velocity.LengthSquared() > 0.0f) | 1138 | if (p2.Velocity.LengthSquared() > 0.0f) |
1128 | p2.CollidingObj = true; | 1139 | p2.CollidingObj = true; |
1129 | break; | 1140 | break; |
@@ -1319,6 +1330,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1319 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && | 1330 | if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && |
1320 | (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) | 1331 | (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) |
1321 | { | 1332 | { |
1333 | p2ExpectedPoints = avatarExpectedContacts; | ||
1322 | // Avatar is moving on terrain, use the movement terrain contact | 1334 | // Avatar is moving on terrain, use the movement terrain contact |
1323 | AvatarMovementTerrainContact.geom = curContact; | 1335 | AvatarMovementTerrainContact.geom = curContact; |
1324 | 1336 | ||
@@ -1332,6 +1344,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1332 | { | 1344 | { |
1333 | if (p2.PhysicsActorType == (int)ActorTypes.Agent) | 1345 | if (p2.PhysicsActorType == (int)ActorTypes.Agent) |
1334 | { | 1346 | { |
1347 | p2ExpectedPoints = avatarExpectedContacts; | ||
1335 | // Avatar is standing on terrain, use the non moving terrain contact | 1348 | // Avatar is standing on terrain, use the non moving terrain contact |
1336 | TerrainContact.geom = curContact; | 1349 | TerrainContact.geom = curContact; |
1337 | 1350 | ||
@@ -1356,9 +1369,18 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1356 | } | 1369 | } |
1357 | 1370 | ||
1358 | if (p2 is OdePrim) | 1371 | if (p2 is OdePrim) |
1359 | material = ((OdePrim)p2).m_material; | 1372 | { |
1360 | 1373 | material = ((OdePrim) p2).m_material; | |
1374 | p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts; | ||
1375 | } | ||
1376 | |||
1377 | // Unnessesary because p1 is defined above | ||
1378 | //if (p1 is OdePrim) | ||
1379 | // { | ||
1380 | // p1ExpectedPoints = ((OdePrim)p1).ExpectedCollisionContacts; | ||
1381 | // } | ||
1361 | //m_log.DebugFormat("Material: {0}", material); | 1382 | //m_log.DebugFormat("Material: {0}", material); |
1383 | |||
1362 | m_materialContacts[material, movintYN].geom = curContact; | 1384 | m_materialContacts[material, movintYN].geom = curContact; |
1363 | 1385 | ||
1364 | if (m_global_contactcount < maxContactsbeforedeath) | 1386 | if (m_global_contactcount < maxContactsbeforedeath) |
@@ -1379,7 +1401,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1379 | int material = (int)Material.Wood; | 1401 | int material = (int)Material.Wood; |
1380 | 1402 | ||
1381 | if (p2 is OdePrim) | 1403 | if (p2 is OdePrim) |
1404 | { | ||
1382 | material = ((OdePrim)p2).m_material; | 1405 | material = ((OdePrim)p2).m_material; |
1406 | p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts; | ||
1407 | } | ||
1383 | 1408 | ||
1384 | //m_log.DebugFormat("Material: {0}", material); | 1409 | //m_log.DebugFormat("Material: {0}", material); |
1385 | m_materialContacts[material, movintYN].geom = curContact; | 1410 | m_materialContacts[material, movintYN].geom = curContact; |
@@ -1429,6 +1454,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1429 | { | 1454 | { |
1430 | if ((p2.PhysicsActorType == (int)ActorTypes.Agent)) | 1455 | if ((p2.PhysicsActorType == (int)ActorTypes.Agent)) |
1431 | { | 1456 | { |
1457 | p2ExpectedPoints = avatarExpectedContacts; | ||
1432 | if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) | 1458 | if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) |
1433 | { | 1459 | { |
1434 | // Avatar is moving on a prim, use the Movement prim contact | 1460 | // Avatar is moving on a prim, use the Movement prim contact |
@@ -1458,7 +1484,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1458 | int material = (int)Material.Wood; | 1484 | int material = (int)Material.Wood; |
1459 | 1485 | ||
1460 | if (p2 is OdePrim) | 1486 | if (p2 is OdePrim) |
1487 | { | ||
1461 | material = ((OdePrim)p2).m_material; | 1488 | material = ((OdePrim)p2).m_material; |
1489 | p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts; | ||
1490 | } | ||
1462 | 1491 | ||
1463 | //m_log.DebugFormat("Material: {0}", material); | 1492 | //m_log.DebugFormat("Material: {0}", material); |
1464 | m_materialContacts[material, 0].geom = curContact; | 1493 | m_materialContacts[material, 0].geom = curContact; |
@@ -1479,8 +1508,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1479 | } | 1508 | } |
1480 | 1509 | ||
1481 | collision_accounting_events(p1, p2, maxDepthContact); | 1510 | collision_accounting_events(p1, p2, maxDepthContact); |
1482 | 1511 | ||
1483 | if (count > geomContactPointsStartthrottle) | 1512 | if (count > ((p1ExpectedPoints + p2ExpectedPoints) * 0.25) + (geomContactPointsStartthrottle)) |
1484 | { | 1513 | { |
1485 | // If there are more then 3 contact points, it's likely | 1514 | // If there are more then 3 contact points, it's likely |
1486 | // that we've got a pile of objects, so ... | 1515 | // that we've got a pile of objects, so ... |