diff options
Diffstat (limited to '')
35 files changed, 959 insertions, 349 deletions
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index a16d174..fd00fe8 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt | |||
@@ -16,7 +16,7 @@ people that make the day to day of OpenSim happen. | |||
16 | * BlueWall (James Hughes) | 16 | * BlueWall (James Hughes) |
17 | * Nebadon Izumi (Michael Cerquoni, OSgrid) | 17 | * Nebadon Izumi (Michael Cerquoni, OSgrid) |
18 | * Snoopy Pfeffer | 18 | * Snoopy Pfeffer |
19 | * Richard Adams (Intel) | 19 | * Robert Adams (Intel) |
20 | 20 | ||
21 | = Core Developers Following the White Rabbit = | 21 | = Core Developers Following the White Rabbit = |
22 | Core developers who have temporarily (we hope) gone chasing the white rabbit. | 22 | Core developers who have temporarily (we hope) gone chasing the white rabbit. |
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/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 130c869..2a513e9 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |||
@@ -407,6 +407,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
407 | 407 | ||
408 | public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) | 408 | public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) |
409 | { | 409 | { |
410 | DetachSingleAttachmentToGround(sp, soLocalId, sp.AbsolutePosition, Quaternion.Identity); | ||
411 | } | ||
412 | |||
413 | public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot) | ||
414 | { | ||
410 | if (!Enabled) | 415 | if (!Enabled) |
411 | return; | 416 | return; |
412 | 417 | ||
@@ -448,7 +453,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
448 | so.FromItemID = UUID.Zero; | 453 | so.FromItemID = UUID.Zero; |
449 | 454 | ||
450 | SceneObjectPart rootPart = so.RootPart; | 455 | SceneObjectPart rootPart = so.RootPart; |
451 | so.AbsolutePosition = sp.AbsolutePosition; | 456 | so.AbsolutePosition = absolutePos; |
457 | if (absoluteRot != Quaternion.Identity) | ||
458 | { | ||
459 | so.UpdateGroupRotationR(absoluteRot); | ||
460 | } | ||
452 | so.AttachedAvatar = UUID.Zero; | 461 | so.AttachedAvatar = UUID.Zero; |
453 | rootPart.SetParentLocalId(0); | 462 | rootPart.SetParentLocalId(0); |
454 | so.ClearPartAttachmentData(); | 463 | so.ClearPartAttachmentData(); |
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 1d6e522..b5b0082 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/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index f3af59a..91eda19 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs | |||
@@ -297,6 +297,45 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | |||
297 | }); | 297 | }); |
298 | } | 298 | } |
299 | } | 299 | } |
300 | else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) | ||
301 | { | ||
302 | UUID destinationFolderID = UUID.Zero; | ||
303 | |||
304 | if (im.binaryBucket != null && im.binaryBucket.Length >= 16) | ||
305 | { | ||
306 | destinationFolderID = new UUID(im.binaryBucket, 0); | ||
307 | } | ||
308 | |||
309 | if (destinationFolderID != UUID.Zero) | ||
310 | { | ||
311 | IInventoryService invService = scene.InventoryService; | ||
312 | |||
313 | UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip | ||
314 | |||
315 | InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); | ||
316 | item = invService.GetItem(item); | ||
317 | InventoryFolderBase folder = null; | ||
318 | |||
319 | if (item != null) // It's an item | ||
320 | { | ||
321 | item.Folder = destinationFolderID; | ||
322 | |||
323 | invService.DeleteItems(item.Owner, new List<UUID>() { item.ID }); | ||
324 | scene.AddInventoryItem(client, item); | ||
325 | } | ||
326 | else | ||
327 | { | ||
328 | folder = new InventoryFolderBase(inventoryID, client.AgentId); | ||
329 | folder = invService.GetFolder(folder); | ||
330 | |||
331 | if (folder != null) // It's a folder | ||
332 | { | ||
333 | folder.ParentID = destinationFolderID; | ||
334 | invService.MoveFolder(folder); | ||
335 | } | ||
336 | } | ||
337 | } | ||
338 | } | ||
300 | else if ( | 339 | else if ( |
301 | im.dialog == (byte)InstantMessageDialog.InventoryDeclined | 340 | im.dialog == (byte)InstantMessageDialog.InventoryDeclined |
302 | || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined) | 341 | || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined) |
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/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs index 65e4c90..fd8d5e3 100755 --- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs +++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs | |||
@@ -1,161 +1,170 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
5 | * Redistribution and use in source and binary forms, with or without | 5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions are met: | 6 | * modification, are permitted provided that the following conditions are met: |
7 | * * Redistributions of source code must retain the above copyright | 7 | * * Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. | 8 | * notice, this list of conditions and the following disclaimer. |
9 | * * Redistributions in binary form must reproduce the above copyright | 9 | * * Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the | 10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. | 11 | * documentation and/or other materials provided with the distribution. |
12 | * * Neither the name of the OpenSimulator Project nor the | 12 | * * Neither the name of the OpenSimulator Project nor the |
13 | * names of its contributors may be used to endorse or promote products | 13 | * names of its contributors may be used to endorse or promote products |
14 | * derived from this software without specific prior written permission. | 14 | * derived from this software without specific prior written permission. |
15 | * | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | 16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | 19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 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 | 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 | 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 | 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. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.IO; | 29 | using System.IO; |
30 | using System.Text; | 30 | using System.Text; |
31 | using log4net; | 31 | using log4net; |
32 | 32 | ||
33 | namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | 33 | namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging |
34 | { | 34 | { |
35 | /// <summary> | 35 | /// <summary> |
36 | /// Class for writing a high performance, high volume log file. | 36 | /// Class for writing a high performance, high volume log file. |
37 | /// Sometimes, to debug, one has a high volume logging to do and the regular | 37 | /// Sometimes, to debug, one has a high volume logging to do and the regular |
38 | /// log file output is not appropriate. | 38 | /// log file output is not appropriate. |
39 | /// Create a new instance with the parameters needed and | 39 | /// Create a new instance with the parameters needed and |
40 | /// call Write() to output a line. Call Close() when finished. | 40 | /// call Write() to output a line. Call Close() when finished. |
41 | /// If created with no parameters, it will not log anything. | 41 | /// If created with no parameters, it will not log anything. |
42 | /// </summary> | 42 | /// </summary> |
43 | public class LogWriter : IDisposable | 43 | public class LogWriter : IDisposable |
44 | { | 44 | { |
45 | public bool Enabled { get; private set; } | 45 | public bool Enabled { get; private set; } |
46 | 46 | ||
47 | private string m_logDirectory = "."; | 47 | private string m_logDirectory = "."; |
48 | private int m_logMaxFileTimeMin = 5; // 5 minutes | 48 | private int m_logMaxFileTimeMin = 5; // 5 minutes |
49 | public String LogFileHeader { get; set; } | 49 | public String LogFileHeader { get; set; } |
50 | 50 | ||
51 | private StreamWriter m_logFile = null; | 51 | private StreamWriter m_logFile = null; |
52 | private TimeSpan m_logFileLife; | 52 | private TimeSpan m_logFileLife; |
53 | private DateTime m_logFileEndTime; | 53 | private DateTime m_logFileEndTime; |
54 | private Object m_logFileWriteLock = new Object(); | 54 | private Object m_logFileWriteLock = new Object(); |
55 | 55 | ||
56 | // set externally when debugging. If let 'null', this does not write any error messages. | 56 | // set externally when debugging. If let 'null', this does not write any error messages. |
57 | public ILog ErrorLogger = null; | 57 | public ILog ErrorLogger = null; |
58 | private string LogHeader = "[LOG WRITER]"; | 58 | private string LogHeader = "[LOG WRITER]"; |
59 | 59 | ||
60 | /// <summary> | 60 | /// <summary> |
61 | /// Create a log writer that will not write anything. Good for when not enabled | 61 | /// Create a log writer that will not write anything. Good for when not enabled |
62 | /// but the write statements are still in the code. | 62 | /// but the write statements are still in the code. |
63 | /// </summary> | 63 | /// </summary> |
64 | public LogWriter() | 64 | public LogWriter() |
65 | { | 65 | { |
66 | Enabled = false; | 66 | Enabled = false; |
67 | m_logFile = null; | 67 | m_logFile = null; |
68 | } | 68 | } |
69 | 69 | ||
70 | /// <summary> | 70 | /// <summary> |
71 | /// Create a log writer instance. | 71 | /// Create a log writer instance. |
72 | /// </summary> | 72 | /// </summary> |
73 | /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param> | 73 | /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param> |
74 | /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param> | 74 | /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param> |
75 | /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param> | 75 | /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param> |
76 | public LogWriter(string dir, string headr, int maxFileTime) | 76 | public LogWriter(string dir, string headr, int maxFileTime) |
77 | { | 77 | { |
78 | m_logDirectory = dir == null ? "." : dir; | 78 | m_logDirectory = dir == null ? "." : dir; |
79 | 79 | ||
80 | LogFileHeader = headr == null ? "log-" : headr; | 80 | LogFileHeader = headr == null ? "log-" : headr; |
81 | 81 | ||
82 | m_logMaxFileTimeMin = maxFileTime; | 82 | m_logMaxFileTimeMin = maxFileTime; |
83 | if (m_logMaxFileTimeMin < 1) | 83 | if (m_logMaxFileTimeMin < 1) |
84 | m_logMaxFileTimeMin = 5; | 84 | m_logMaxFileTimeMin = 5; |
85 | 85 | ||
86 | m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); | 86 | m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); |
87 | m_logFileEndTime = DateTime.Now + m_logFileLife; | 87 | m_logFileEndTime = DateTime.Now + m_logFileLife; |
88 | 88 | ||
89 | Enabled = true; | 89 | Enabled = true; |
90 | } | 90 | } |
91 | 91 | ||
92 | public void Dispose() | 92 | public void Dispose() |
93 | { | 93 | { |
94 | this.Close(); | 94 | this.Close(); |
95 | } | 95 | } |
96 | 96 | ||
97 | public void Close() | 97 | public void Close() |
98 | { | 98 | { |
99 | Enabled = false; | 99 | Enabled = false; |
100 | if (m_logFile != null) | 100 | if (m_logFile != null) |
101 | { | 101 | { |
102 | m_logFile.Close(); | 102 | m_logFile.Close(); |
103 | m_logFile.Dispose(); | 103 | m_logFile.Dispose(); |
104 | m_logFile = null; | 104 | m_logFile = null; |
105 | } | 105 | } |
106 | } | 106 | } |
107 | 107 | ||
108 | public void Write(string line, params object[] args) | 108 | public void Write(string line, params object[] args) |
109 | { | 109 | { |
110 | if (!Enabled) return; | 110 | if (!Enabled) return; |
111 | Write(String.Format(line, args)); | 111 | Write(String.Format(line, args)); |
112 | } | 112 | } |
113 | 113 | ||
114 | public void Write(string line) | 114 | public void Flush() |
115 | { | 115 | { |
116 | if (!Enabled) return; | 116 | if (!Enabled) return; |
117 | try | 117 | if (m_logFile != null) |
118 | { | 118 | { |
119 | lock (m_logFileWriteLock) | 119 | m_logFile.Flush(); |
120 | { | 120 | } |
121 | DateTime now = DateTime.Now; | 121 | } |
122 | if (m_logFile == null || now > m_logFileEndTime) | 122 | |
123 | { | 123 | public void Write(string line) |
124 | if (m_logFile != null) | 124 | { |
125 | { | 125 | if (!Enabled) return; |
126 | m_logFile.Close(); | 126 | try |
127 | m_logFile.Dispose(); | 127 | { |
128 | m_logFile = null; | 128 | lock (m_logFileWriteLock) |
129 | } | 129 | { |
130 | 130 | DateTime now = DateTime.Now; | |
131 | // First log file or time has expired, start writing to a new log file | 131 | if (m_logFile == null || now > m_logFileEndTime) |
132 | m_logFileEndTime = now + m_logFileLife; | 132 | { |
133 | string path = (m_logDirectory.Length > 0 ? m_logDirectory | 133 | if (m_logFile != null) |
134 | + System.IO.Path.DirectorySeparatorChar.ToString() : "") | 134 | { |
135 | + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); | 135 | m_logFile.Close(); |
136 | m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); | 136 | m_logFile.Dispose(); |
137 | } | 137 | m_logFile = null; |
138 | if (m_logFile != null) | 138 | } |
139 | { | 139 | |
140 | StringBuilder buff = new StringBuilder(line.Length + 25); | 140 | // First log file or time has expired, start writing to a new log file |
141 | buff.Append(now.ToString("yyyyMMddHHmmssfff")); | 141 | m_logFileEndTime = now + m_logFileLife; |
142 | // buff.Append(now.ToString("yyyyMMddHHmmss")); | 142 | string path = (m_logDirectory.Length > 0 ? m_logDirectory |
143 | buff.Append(","); | 143 | + System.IO.Path.DirectorySeparatorChar.ToString() : "") |
144 | buff.Append(line); | 144 | + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); |
145 | buff.Append("\r\n"); | 145 | m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); |
146 | m_logFile.Write(buff.ToString()); | 146 | } |
147 | } | 147 | if (m_logFile != null) |
148 | } | 148 | { |
149 | } | 149 | StringBuilder buff = new StringBuilder(line.Length + 25); |
150 | catch (Exception e) | 150 | buff.Append(now.ToString("yyyyMMddHHmmssfff")); |
151 | { | 151 | // buff.Append(now.ToString("yyyyMMddHHmmss")); |
152 | if (ErrorLogger != null) | 152 | buff.Append(","); |
153 | { | 153 | buff.Append(line); |
154 | ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); | 154 | buff.Append("\r\n"); |
155 | } | 155 | m_logFile.Write(buff.ToString()); |
156 | Enabled = false; | 156 | } |
157 | } | 157 | } |
158 | return; | 158 | } |
159 | } | 159 | catch (Exception e) |
160 | } | 160 | { |
161 | } \ No newline at end of file | 161 | if (ErrorLogger != null) |
162 | { | ||
163 | ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); | ||
164 | } | ||
165 | Enabled = false; | ||
166 | } | ||
167 | return; | ||
168 | } | ||
169 | } | ||
170 | } | ||
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 8155eab..620ec22 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs | |||
@@ -109,6 +109,15 @@ namespace OpenSim.Region.Framework.Interfaces | |||
109 | void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID); | 109 | void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID); |
110 | 110 | ||
111 | /// <summary> | 111 | /// <summary> |
112 | /// Detach the given item to the ground at the specified coordinates & rotation | ||
113 | /// </summary> | ||
114 | /// <param name="sp"></param> | ||
115 | /// <param name="objectLocalID"></param> | ||
116 | /// <param name="absolutePos"></param> | ||
117 | /// <param name="absoluteRot"></param> | ||
118 | void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID, Vector3 absolutePos, Quaternion absoluteRot); | ||
119 | |||
120 | /// <summary> | ||
112 | /// Detach the given attachment so that it remains in the user's inventory. | 121 | /// Detach the given attachment so that it remains in the user's inventory. |
113 | /// </summary> | 122 | /// </summary> |
114 | /// <param name="sp">/param> | 123 | /// <param name="sp">/param> |
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 ff53f45..bb33f07 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs | |||
@@ -408,13 +408,19 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
408 | { | 408 | { |
409 | lock (m_animations) | 409 | lock (m_animations) |
410 | { | 410 | { |
411 | CurrentMovementAnimation = DetermineMovementAnimation(); | 411 | string newMovementAnimation = DetermineMovementAnimation(); |
412 | if (CurrentMovementAnimation != newMovementAnimation) | ||
413 | { | ||
414 | CurrentMovementAnimation = DetermineMovementAnimation(); | ||
412 | 415 | ||
413 | // m_log.DebugFormat( | 416 | // m_log.DebugFormat( |
414 | // "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()", | 417 | // "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()", |
415 | // CurrentMovementAnimation, m_scenePresence.Name); | 418 | // CurrentMovementAnimation, m_scenePresence.Name); |
416 | 419 | ||
417 | TrySetMovementAnimation(CurrentMovementAnimation); | 420 | // Only set it if it's actually changed, give a script |
421 | // a chance to stop a default animation | ||
422 | TrySetMovementAnimation(CurrentMovementAnimation); | ||
423 | } | ||
418 | } | 424 | } |
419 | } | 425 | } |
420 | 426 | ||
@@ -536,4 +542,4 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
536 | SendAnimPack(animIDs, sequenceNums, objectIDs); | 542 | SendAnimPack(animIDs, sequenceNums, objectIDs); |
537 | } | 543 | } |
538 | } | 544 | } |
539 | } \ No newline at end of file | 545 | } |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 2e03874..0a4aa4a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -5545,6 +5545,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
5545 | 5545 | ||
5546 | public void StoreExtraSetting(string name, string val) | 5546 | public void StoreExtraSetting(string name, string val) |
5547 | { | 5547 | { |
5548 | if (m_extraSettings == null) | ||
5549 | return; | ||
5550 | |||
5548 | string oldVal; | 5551 | string oldVal; |
5549 | 5552 | ||
5550 | if (m_extraSettings.TryGetValue(name, out oldVal)) | 5553 | if (m_extraSettings.TryGetValue(name, out oldVal)) |
@@ -5562,6 +5565,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
5562 | 5565 | ||
5563 | public void RemoveExtraSetting(string name) | 5566 | public void RemoveExtraSetting(string name) |
5564 | { | 5567 | { |
5568 | if (m_extraSettings == null) | ||
5569 | return; | ||
5570 | |||
5565 | if (!m_extraSettings.ContainsKey(name)) | 5571 | if (!m_extraSettings.ContainsKey(name)) |
5566 | return; | 5572 | return; |
5567 | 5573 | ||
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index 96317c3..2addb5b 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> |
@@ -225,6 +236,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
225 | 236 | ||
226 | if (StatsManager.SimExtraStats != null) | 237 | if (StatsManager.SimExtraStats != null) |
227 | OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; | 238 | OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; |
239 | |||
240 | /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit | ||
241 | /// longer than ideal (which in itself is a concern). | ||
242 | SlowFramesStatReportThreshold = (int)Math.Ceiling(m_scene.MinFrameTime * 1000 * 1.2); | ||
243 | |||
244 | SlowFramesStat | ||
245 | = new Stat( | ||
246 | "SlowFrames", | ||
247 | "Slow Frames", | ||
248 | " frames", | ||
249 | "scene", | ||
250 | m_scene.Name, | ||
251 | StatVerbosity.Info, | ||
252 | "Number of frames where frame time has been significantly longer than the desired frame time."); | ||
253 | |||
254 | StatsManager.RegisterStat(SlowFramesStat); | ||
228 | } | 255 | } |
229 | 256 | ||
230 | public void Close() | 257 | public void Close() |
@@ -418,6 +445,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
418 | lock (m_lastReportedExtraSimStats) | 445 | lock (m_lastReportedExtraSimStats) |
419 | { | 446 | { |
420 | m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; | 447 | m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; |
448 | m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value; | ||
421 | 449 | ||
422 | Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats(); | 450 | Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats(); |
423 | 451 | ||
@@ -535,6 +563,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
535 | public void addFrameMS(int ms) | 563 | public void addFrameMS(int ms) |
536 | { | 564 | { |
537 | m_frameMS += ms; | 565 | m_frameMS += ms; |
566 | |||
567 | // At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit | ||
568 | // longer than ideal due to the inaccuracy of the Sleep in Scene.Update() (which in itself is a concern). | ||
569 | if (ms > SlowFramesStatReportThreshold) | ||
570 | SlowFramesStat.Value++; | ||
538 | } | 571 | } |
539 | 572 | ||
540 | public void AddSpareMS(int ms) | 573 | public void AddSpareMS(int ms) |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index b88ec3c..2a52e01 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -218,6 +218,18 @@ public class BSCharacter : BSPhysObject | |||
218 | }); | 218 | }); |
219 | } | 219 | } |
220 | } | 220 | } |
221 | public override OMV.Vector3 ForcePosition { | ||
222 | get { | ||
223 | _position = BulletSimAPI.GetPosition2(BSBody.ptr); | ||
224 | return _position; | ||
225 | } | ||
226 | set { | ||
227 | _position = value; | ||
228 | PositionSanityCheck(); | ||
229 | BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); | ||
230 | } | ||
231 | } | ||
232 | |||
221 | 233 | ||
222 | // Check that the current position is sane and, if not, modify the position to make it so. | 234 | // Check that the current position is sane and, if not, modify the position to make it so. |
223 | // Check for being below terrain and being out of bounds. | 235 | // Check for being below terrain and being out of bounds. |
@@ -234,6 +246,15 @@ public class BSCharacter : BSPhysObject | |||
234 | _position.Z = terrainHeight + 2.0f; | 246 | _position.Z = terrainHeight + 2.0f; |
235 | ret = true; | 247 | ret = true; |
236 | } | 248 | } |
249 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) | ||
250 | { | ||
251 | float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); | ||
252 | if (Position.Z < waterHeight) | ||
253 | { | ||
254 | _position.Z = waterHeight; | ||
255 | ret = true; | ||
256 | } | ||
257 | } | ||
237 | 258 | ||
238 | // TODO: check for out of bounds | 259 | // TODO: check for out of bounds |
239 | return ret; | 260 | return ret; |
@@ -242,18 +263,22 @@ public class BSCharacter : BSPhysObject | |||
242 | // A version of the sanity check that also makes sure a new position value is | 263 | // A version of the sanity check that also makes sure a new position value is |
243 | // pushed back to the physics engine. This routine would be used by anyone | 264 | // pushed back to the physics engine. This routine would be used by anyone |
244 | // who is not already pushing the value. | 265 | // who is not already pushing the value. |
245 | private bool PositionSanityCheck2() | 266 | private bool PositionSanityCheck2(bool atTaintTime) |
246 | { | 267 | { |
247 | bool ret = false; | 268 | bool ret = false; |
248 | if (PositionSanityCheck()) | 269 | if (PositionSanityCheck()) |
249 | { | 270 | { |
250 | // The new position value must be pushed into the physics engine but we can't | 271 | // The new position value must be pushed into the physics engine but we can't |
251 | // just assign to "Position" because of potential call loops. | 272 | // just assign to "Position" because of potential call loops. |
252 | PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", delegate() | 273 | BSScene.TaintCallback sanityOperation = delegate() |
253 | { | 274 | { |
254 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 275 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
255 | BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); | 276 | BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); |
256 | }); | 277 | }; |
278 | if (atTaintTime) | ||
279 | sanityOperation(); | ||
280 | else | ||
281 | PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation); | ||
257 | ret = true; | 282 | ret = true; |
258 | } | 283 | } |
259 | return ret; | 284 | return ret; |
@@ -333,6 +358,20 @@ public class BSCharacter : BSPhysObject | |||
333 | }); | 358 | }); |
334 | } | 359 | } |
335 | } | 360 | } |
361 | // Go directly to Bullet to get/set the value. | ||
362 | public override OMV.Quaternion ForceOrientation | ||
363 | { | ||
364 | get | ||
365 | { | ||
366 | _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr); | ||
367 | return _orientation; | ||
368 | } | ||
369 | set | ||
370 | { | ||
371 | _orientation = value; | ||
372 | BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); | ||
373 | } | ||
374 | } | ||
336 | public override int PhysicsActorType { | 375 | public override int PhysicsActorType { |
337 | get { return _physicsActorType; } | 376 | get { return _physicsActorType; } |
338 | set { _physicsActorType = value; | 377 | set { _physicsActorType = value; |
@@ -378,7 +417,16 @@ public class BSCharacter : BSPhysObject | |||
378 | set { _collidingObj = value; } | 417 | set { _collidingObj = value; } |
379 | } | 418 | } |
380 | public override bool FloatOnWater { | 419 | public override bool FloatOnWater { |
381 | set { _floatOnWater = value; } | 420 | set { |
421 | _floatOnWater = value; | ||
422 | PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() | ||
423 | { | ||
424 | if (_floatOnWater) | ||
425 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); | ||
426 | else | ||
427 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); | ||
428 | }); | ||
429 | } | ||
382 | } | 430 | } |
383 | public override OMV.Vector3 RotationalVelocity { | 431 | public override OMV.Vector3 RotationalVelocity { |
384 | get { return _rotationalVelocity; } | 432 | get { return _rotationalVelocity; } |
@@ -493,15 +541,14 @@ public class BSCharacter : BSPhysObject | |||
493 | _velocity = entprop.Velocity; | 541 | _velocity = entprop.Velocity; |
494 | _acceleration = entprop.Acceleration; | 542 | _acceleration = entprop.Acceleration; |
495 | _rotationalVelocity = entprop.RotationalVelocity; | 543 | _rotationalVelocity = entprop.RotationalVelocity; |
544 | // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. | ||
545 | PositionSanityCheck2(true); | ||
546 | |||
496 | // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. | 547 | // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. |
497 | // base.RequestPhysicsterseUpdate(); | 548 | // base.RequestPhysicsterseUpdate(); |
498 | 549 | ||
499 | // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. | 550 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", |
500 | PositionSanityCheck2(); | 551 | LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); |
501 | |||
502 | float heightHere = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug | ||
503 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}", | ||
504 | LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere); | ||
505 | } | 552 | } |
506 | } | 553 | } |
507 | } | 554 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 65b38d6..4ba2f62 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |||
@@ -92,7 +92,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
92 | private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate | 92 | private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate |
93 | private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate | 93 | private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate |
94 | private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body | 94 | private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body |
95 | // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body | 95 | private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body |
96 | 96 | ||
97 | //Deflection properties | 97 | //Deflection properties |
98 | // private float m_angularDeflectionEfficiency = 0; | 98 | // private float m_angularDeflectionEfficiency = 0; |
@@ -138,74 +138,55 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
138 | switch (pParam) | 138 | switch (pParam) |
139 | { | 139 | { |
140 | case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: | 140 | case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: |
141 | if (pValue < 0.01f) pValue = 0.01f; | 141 | // m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); |
142 | // m_angularDeflectionEfficiency = pValue; | ||
143 | break; | 142 | break; |
144 | case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: | 143 | case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: |
145 | if (pValue < 0.01f) pValue = 0.01f; | 144 | // m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); |
146 | // m_angularDeflectionTimescale = pValue; | ||
147 | break; | 145 | break; |
148 | case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: | 146 | case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: |
149 | if (pValue < 0.01f) pValue = 0.01f; | 147 | m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f); |
150 | m_angularMotorDecayTimescale = pValue; | ||
151 | break; | 148 | break; |
152 | case Vehicle.ANGULAR_MOTOR_TIMESCALE: | 149 | case Vehicle.ANGULAR_MOTOR_TIMESCALE: |
153 | if (pValue < 0.01f) pValue = 0.01f; | 150 | m_angularMotorTimescale = Math.Max(pValue, 0.01f); |
154 | m_angularMotorTimescale = pValue; | ||
155 | break; | 151 | break; |
156 | case Vehicle.BANKING_EFFICIENCY: | 152 | case Vehicle.BANKING_EFFICIENCY: |
157 | if (pValue < 0.01f) pValue = 0.01f; | 153 | // m_bankingEfficiency = Math.Max(pValue, 0.01f); |
158 | // m_bankingEfficiency = pValue; | ||
159 | break; | 154 | break; |
160 | case Vehicle.BANKING_MIX: | 155 | case Vehicle.BANKING_MIX: |
161 | if (pValue < 0.01f) pValue = 0.01f; | 156 | // m_bankingMix = Math.Max(pValue, 0.01f); |
162 | // m_bankingMix = pValue; | ||
163 | break; | 157 | break; |
164 | case Vehicle.BANKING_TIMESCALE: | 158 | case Vehicle.BANKING_TIMESCALE: |
165 | if (pValue < 0.01f) pValue = 0.01f; | 159 | // m_bankingTimescale = Math.Max(pValue, 0.01f); |
166 | // m_bankingTimescale = pValue; | ||
167 | break; | 160 | break; |
168 | case Vehicle.BUOYANCY: | 161 | case Vehicle.BUOYANCY: |
169 | if (pValue < -1f) pValue = -1f; | 162 | m_VehicleBuoyancy = Math.Max(-1f, Math.Min(pValue, 1f)); |
170 | if (pValue > 1f) pValue = 1f; | ||
171 | m_VehicleBuoyancy = pValue; | ||
172 | break; | 163 | break; |
173 | // case Vehicle.HOVER_EFFICIENCY: | 164 | // case Vehicle.HOVER_EFFICIENCY: |
174 | // if (pValue < 0f) pValue = 0f; | 165 | // m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f)); |
175 | // if (pValue > 1f) pValue = 1f; | ||
176 | // m_VhoverEfficiency = pValue; | ||
177 | // break; | 166 | // break; |
178 | case Vehicle.HOVER_HEIGHT: | 167 | case Vehicle.HOVER_HEIGHT: |
179 | m_VhoverHeight = pValue; | 168 | m_VhoverHeight = pValue; |
180 | break; | 169 | break; |
181 | case Vehicle.HOVER_TIMESCALE: | 170 | case Vehicle.HOVER_TIMESCALE: |
182 | if (pValue < 0.01f) pValue = 0.01f; | 171 | m_VhoverTimescale = Math.Max(pValue, 0.01f); |
183 | m_VhoverTimescale = pValue; | ||
184 | break; | 172 | break; |
185 | case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: | 173 | case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: |
186 | if (pValue < 0.01f) pValue = 0.01f; | 174 | // m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); |
187 | // m_linearDeflectionEfficiency = pValue; | ||
188 | break; | 175 | break; |
189 | case Vehicle.LINEAR_DEFLECTION_TIMESCALE: | 176 | case Vehicle.LINEAR_DEFLECTION_TIMESCALE: |
190 | if (pValue < 0.01f) pValue = 0.01f; | 177 | // m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); |
191 | // m_linearDeflectionTimescale = pValue; | ||
192 | break; | 178 | break; |
193 | case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: | 179 | case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: |
194 | if (pValue < 0.01f) pValue = 0.01f; | 180 | m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f); |
195 | m_linearMotorDecayTimescale = pValue; | ||
196 | break; | 181 | break; |
197 | case Vehicle.LINEAR_MOTOR_TIMESCALE: | 182 | case Vehicle.LINEAR_MOTOR_TIMESCALE: |
198 | if (pValue < 0.01f) pValue = 0.01f; | 183 | m_linearMotorTimescale = Math.Max(pValue, 0.01f); |
199 | m_linearMotorTimescale = pValue; | ||
200 | break; | 184 | break; |
201 | case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: | 185 | case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: |
202 | if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable | 186 | m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f)); |
203 | if (pValue > 1.0f) pValue = 1.0f; | ||
204 | m_verticalAttractionEfficiency = pValue; | ||
205 | break; | 187 | break; |
206 | case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: | 188 | case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: |
207 | if (pValue < 0.01f) pValue = 0.01f; | 189 | m_verticalAttractionTimescale = Math.Max(pValue, 0.01f); |
208 | m_verticalAttractionTimescale = pValue; | ||
209 | break; | 190 | break; |
210 | 191 | ||
211 | // These are vector properties but the engine lets you use a single float value to | 192 | // These are vector properties but the engine lets you use a single float value to |
@@ -371,8 +352,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
371 | // m_bankingMix = 1; | 352 | // m_bankingMix = 1; |
372 | // m_bankingTimescale = 1; | 353 | // m_bankingTimescale = 1; |
373 | // m_referenceFrame = Quaternion.Identity; | 354 | // m_referenceFrame = Quaternion.Identity; |
374 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | | 355 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
375 | VehicleFlag.LIMIT_MOTOR_UP); | 356 | | VehicleFlag.LIMIT_ROLL_ONLY |
357 | | VehicleFlag.LIMIT_MOTOR_UP); | ||
376 | m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); | 358 | m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); |
377 | m_flags |= (VehicleFlag.HOVER_UP_ONLY); | 359 | m_flags |= (VehicleFlag.HOVER_UP_ONLY); |
378 | break; | 360 | break; |
@@ -399,12 +381,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
399 | // m_bankingMix = 0.8f; | 381 | // m_bankingMix = 0.8f; |
400 | // m_bankingTimescale = 1; | 382 | // m_bankingTimescale = 1; |
401 | // m_referenceFrame = Quaternion.Identity; | 383 | // m_referenceFrame = Quaternion.Identity; |
402 | m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | | 384 | m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
403 | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); | 385 | | VehicleFlag.HOVER_GLOBAL_HEIGHT |
404 | m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); | 386 | | VehicleFlag.LIMIT_ROLL_ONLY |
405 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | | 387 | | VehicleFlag.HOVER_UP_ONLY); |
406 | VehicleFlag.LIMIT_MOTOR_UP); | 388 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
407 | m_flags |= (VehicleFlag.HOVER_WATER_ONLY); | 389 | | VehicleFlag.LIMIT_MOTOR_UP |
390 | | VehicleFlag.HOVER_WATER_ONLY); | ||
408 | break; | 391 | break; |
409 | case Vehicle.TYPE_AIRPLANE: | 392 | case Vehicle.TYPE_AIRPLANE: |
410 | m_linearFrictionTimescale = new Vector3(200, 10, 5); | 393 | m_linearFrictionTimescale = new Vector3(200, 10, 5); |
@@ -429,9 +412,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
429 | // m_bankingMix = 0.7f; | 412 | // m_bankingMix = 0.7f; |
430 | // m_bankingTimescale = 2; | 413 | // m_bankingTimescale = 2; |
431 | // m_referenceFrame = Quaternion.Identity; | 414 | // m_referenceFrame = Quaternion.Identity; |
432 | m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | | 415 | m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
433 | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); | 416 | | VehicleFlag.HOVER_TERRAIN_ONLY |
434 | m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); | 417 | | VehicleFlag.HOVER_GLOBAL_HEIGHT |
418 | | VehicleFlag.HOVER_UP_ONLY | ||
419 | | VehicleFlag.NO_DEFLECTION_UP | ||
420 | | VehicleFlag.LIMIT_MOTOR_UP); | ||
435 | m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); | 421 | m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); |
436 | break; | 422 | break; |
437 | case Vehicle.TYPE_BALLOON: | 423 | case Vehicle.TYPE_BALLOON: |
@@ -457,11 +443,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
457 | // m_bankingMix = 0.7f; | 443 | // m_bankingMix = 0.7f; |
458 | // m_bankingTimescale = 5; | 444 | // m_bankingTimescale = 5; |
459 | // m_referenceFrame = Quaternion.Identity; | 445 | // m_referenceFrame = Quaternion.Identity; |
460 | m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | | 446 | m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
461 | VehicleFlag.HOVER_UP_ONLY); | 447 | | VehicleFlag.HOVER_TERRAIN_ONLY |
462 | m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); | 448 | | VehicleFlag.HOVER_UP_ONLY |
463 | m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); | 449 | | VehicleFlag.NO_DEFLECTION_UP |
464 | m_flags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); | 450 | | VehicleFlag.LIMIT_MOTOR_UP); |
451 | m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | ||
452 | | VehicleFlag.HOVER_GLOBAL_HEIGHT); | ||
465 | break; | 453 | break; |
466 | } | 454 | } |
467 | }//end SetDefaultsForType | 455 | }//end SetDefaultsForType |
@@ -470,7 +458,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
470 | // Do any updating needed for a vehicle | 458 | // Do any updating needed for a vehicle |
471 | public void Refresh() | 459 | public void Refresh() |
472 | { | 460 | { |
473 | if (Type == Vehicle.TYPE_NONE) return; | 461 | if (!IsActive) |
462 | return; | ||
474 | 463 | ||
475 | // Set the prim's inertia to zero. The vehicle code handles that and this | 464 | // Set the prim's inertia to zero. The vehicle code handles that and this |
476 | // removes the torque action introduced by Bullet. | 465 | // removes the torque action introduced by Bullet. |
@@ -489,7 +478,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
489 | LimitRotation(pTimestep); | 478 | LimitRotation(pTimestep); |
490 | 479 | ||
491 | // remember the position so next step we can limit absolute movement effects | 480 | // remember the position so next step we can limit absolute movement effects |
492 | m_lastPositionVector = Prim.Position; | 481 | m_lastPositionVector = Prim.ForcePosition; |
493 | 482 | ||
494 | VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", | 483 | VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", |
495 | Prim.LocalID, Prim.Position, Prim.Force, Prim.Velocity, Prim.RotationalVelocity); | 484 | Prim.LocalID, Prim.Position, Prim.Force, Prim.Velocity, Prim.RotationalVelocity); |
@@ -543,7 +532,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
543 | } | 532 | } |
544 | 533 | ||
545 | // convert requested object velocity to object relative vector | 534 | // convert requested object velocity to object relative vector |
546 | Quaternion rotq = Prim.Orientation; | 535 | Quaternion rotq = Prim.ForceOrientation; |
547 | m_newVelocity = m_lastLinearVelocityVector * rotq; | 536 | m_newVelocity = m_lastLinearVelocityVector * rotq; |
548 | 537 | ||
549 | // Add the various forces into m_dir which will be our new direction vector (velocity) | 538 | // Add the various forces into m_dir which will be our new direction vector (velocity) |
@@ -560,19 +549,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
560 | m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity | 549 | m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity |
561 | */ | 550 | */ |
562 | 551 | ||
563 | Vector3 pos = Prim.Position; | 552 | Vector3 pos = Prim.ForcePosition; |
564 | // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); | 553 | // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); |
565 | 554 | ||
566 | // If below the terrain, move us above the ground a little. | 555 | // If below the terrain, move us above the ground a little. |
567 | float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); | 556 | float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); |
568 | // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. | 557 | // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. |
569 | // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. | 558 | // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. |
570 | // Vector3 rotatedSize = m_prim.Size * m_prim.Orientation; | 559 | // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation; |
571 | // if (rotatedSize.Z < terrainHeight) | 560 | // if (rotatedSize.Z < terrainHeight) |
572 | if (pos.Z < terrainHeight) | 561 | if (pos.Z < terrainHeight) |
573 | { | 562 | { |
574 | pos.Z = terrainHeight + 2; | 563 | pos.Z = terrainHeight + 2; |
575 | Prim.Position = pos; | 564 | Prim.ForcePosition = pos; |
576 | VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos); | 565 | VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos); |
577 | } | 566 | } |
578 | 567 | ||
@@ -602,7 +591,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
602 | { | 591 | { |
603 | if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) | 592 | if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) |
604 | { | 593 | { |
605 | Prim.Position = pos; | 594 | Prim.ForcePosition = pos; |
606 | } | 595 | } |
607 | } | 596 | } |
608 | else | 597 | else |
@@ -654,12 +643,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
654 | } | 643 | } |
655 | if (changed) | 644 | if (changed) |
656 | { | 645 | { |
657 | Prim.Position = pos; | 646 | Prim.ForcePosition = pos; |
658 | VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", | 647 | VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", |
659 | Prim.LocalID, m_BlockingEndPoint, posChange, pos); | 648 | Prim.LocalID, m_BlockingEndPoint, posChange, pos); |
660 | } | 649 | } |
661 | } | 650 | } |
662 | 651 | ||
652 | // Limit absolute vertical change | ||
663 | float Zchange = Math.Abs(posChange.Z); | 653 | float Zchange = Math.Abs(posChange.Z); |
664 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) | 654 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) |
665 | { | 655 | { |
@@ -678,6 +668,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
678 | grav.Z = (float)(grav.Z * 1.037125); | 668 | grav.Z = (float)(grav.Z * 1.037125); |
679 | VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", Prim.LocalID, grav); | 669 | VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", Prim.LocalID, grav); |
680 | } | 670 | } |
671 | |||
672 | // If not changing some axis, reduce out velocity | ||
681 | if ((m_flags & (VehicleFlag.NO_X)) != 0) | 673 | if ((m_flags & (VehicleFlag.NO_X)) != 0) |
682 | m_newVelocity.X = 0; | 674 | m_newVelocity.X = 0; |
683 | if ((m_flags & (VehicleFlag.NO_Y)) != 0) | 675 | if ((m_flags & (VehicleFlag.NO_Y)) != 0) |
@@ -720,19 +712,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
720 | // a newly set velocity, this routine steps the value from the previous | 712 | // a newly set velocity, this routine steps the value from the previous |
721 | // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection). | 713 | // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection). |
722 | // There are m_angularMotorApply steps. | 714 | // There are m_angularMotorApply steps. |
723 | Vector3 origAngularVelocity = m_angularMotorVelocity; | 715 | Vector3 origVel = m_angularMotorVelocity; |
716 | Vector3 origDir = m_angularMotorDirection; | ||
717 | |||
724 | // ramp up to new value | 718 | // ramp up to new value |
725 | // current velocity += error / ( time to get there / step interval) | 719 | // new velocity += error / ( time to get there / step interval) |
726 | // requested speed - last motor speed | 720 | // requested speed - last motor speed |
727 | m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); | 721 | m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); |
728 | m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); | 722 | m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); |
729 | m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); | 723 | m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); |
730 | 724 | ||
731 | VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},dir={5},vel={6}", | 725 | VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},origDir={5},vel={6}", |
732 | Prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); | 726 | Prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity); |
733 | 727 | ||
734 | // This is done so that if script request rate is less than phys frame rate the expected | ||
735 | // velocity may still be acheived. | ||
736 | m_angularMotorApply--; | 728 | m_angularMotorApply--; |
737 | } | 729 | } |
738 | else | 730 | else |
@@ -746,25 +738,32 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
746 | 738 | ||
747 | // Vertical attractor section | 739 | // Vertical attractor section |
748 | Vector3 vertattr = Vector3.Zero; | 740 | Vector3 vertattr = Vector3.Zero; |
749 | if (m_verticalAttractionTimescale < 300) | 741 | Vector3 deflection = Vector3.Zero; |
742 | Vector3 banking = Vector3.Zero; | ||
743 | |||
744 | if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) | ||
750 | { | 745 | { |
751 | float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep); | 746 | float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep); |
747 | VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); | ||
748 | |||
752 | // get present body rotation | 749 | // get present body rotation |
753 | Quaternion rotq = Prim.Orientation; | 750 | Quaternion rotq = Prim.ForceOrientation; |
754 | // make a vector pointing up | 751 | // vector pointing up |
755 | Vector3 verterr = Vector3.Zero; | 752 | Vector3 verterr = Vector3.Zero; |
756 | verterr.Z = 1.0f; | 753 | verterr.Z = 1.0f; |
754 | |||
757 | // rotate it to Body Angle | 755 | // rotate it to Body Angle |
758 | verterr = verterr * rotq; | 756 | verterr = verterr * rotq; |
759 | // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. | 757 | // verterr.X and .Y are the World error amounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. |
760 | // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go | 758 | // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go |
761 | // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. | 759 | // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. |
760 | |||
761 | // Error is 0 (no error) to +/- 2 (max error) | ||
762 | if (verterr.Z < 0.0f) | 762 | if (verterr.Z < 0.0f) |
763 | { | 763 | { |
764 | verterr.X = 2.0f - verterr.X; | 764 | verterr.X = 2.0f - verterr.X; |
765 | verterr.Y = 2.0f - verterr.Y; | 765 | verterr.Y = 2.0f - verterr.Y; |
766 | } | 766 | } |
767 | // Error is 0 (no error) to +/- 2 (max error) | ||
768 | // scale it by VAservo | 767 | // scale it by VAservo |
769 | verterr = verterr * VAservo; | 768 | verterr = verterr * VAservo; |
770 | 769 | ||
@@ -784,7 +783,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
784 | 783 | ||
785 | } // else vertical attractor is off | 784 | } // else vertical attractor is off |
786 | 785 | ||
787 | // m_lastVertAttractor = vertattr; | 786 | m_lastVertAttractor = vertattr; |
788 | 787 | ||
789 | // Bank section tba | 788 | // Bank section tba |
790 | 789 | ||
@@ -818,7 +817,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
818 | 817 | ||
819 | internal void LimitRotation(float timestep) | 818 | internal void LimitRotation(float timestep) |
820 | { | 819 | { |
821 | Quaternion rotq = Prim.Orientation; | 820 | Quaternion rotq = Prim.ForceOrientation; |
822 | Quaternion m_rot = rotq; | 821 | Quaternion m_rot = rotq; |
823 | bool changed = false; | 822 | bool changed = false; |
824 | if (m_RollreferenceFrame != Quaternion.Identity) | 823 | if (m_RollreferenceFrame != Quaternion.Identity) |
@@ -853,7 +852,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
853 | } | 852 | } |
854 | if (changed) | 853 | if (changed) |
855 | { | 854 | { |
856 | Prim.Orientation = m_rot; | 855 | Prim.ForceOrientation = m_rot; |
857 | VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); | 856 | VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); |
858 | } | 857 | } |
859 | 858 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 4f225ae..3e82642 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -34,7 +34,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
34 | { | 34 | { |
35 | public class BSLinkset | 35 | public class BSLinkset |
36 | { | 36 | { |
37 | private static string LogHeader = "[BULLETSIM LINKSET]"; | 37 | // private static string LogHeader = "[BULLETSIM LINKSET]"; |
38 | 38 | ||
39 | public BSPhysObject LinksetRoot { get; protected set; } | 39 | public BSPhysObject LinksetRoot { get; protected set; } |
40 | 40 | ||
@@ -331,21 +331,21 @@ public class BSLinkset | |||
331 | m_children.Add(child); | 331 | m_children.Add(child); |
332 | 332 | ||
333 | BSPhysObject rootx = LinksetRoot; // capture the root and body as of now | 333 | BSPhysObject rootx = LinksetRoot; // capture the root and body as of now |
334 | BulletBody rootBodyx = LinksetRoot.BSBody; | ||
335 | BSPhysObject childx = child; | 334 | BSPhysObject childx = child; |
336 | BulletBody childBodyx = child.BSBody; | ||
337 | 335 | ||
338 | DetailLog("{0},AddChildToLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", | 336 | DetailLog("{0},AddChildToLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", |
339 | rootx.LocalID, | 337 | rootx.LocalID, |
340 | rootx.LocalID, rootBodyx.ptr.ToString("X"), | 338 | rootx.LocalID, rootx.BSBody.ptr.ToString("X"), |
341 | childx.LocalID, childBodyx.ptr.ToString("X")); | 339 | childx.LocalID, childx.BSBody.ptr.ToString("X")); |
342 | 340 | ||
343 | PhysicsScene.TaintedObject("AddChildToLinkset", delegate() | 341 | PhysicsScene.TaintedObject("AddChildToLinkset", delegate() |
344 | { | 342 | { |
345 | DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); | 343 | DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); |
346 | // build the physical binding between me and the child | 344 | // build the physical binding between me and the child |
347 | m_taintChildren.Add(childx); | 345 | m_taintChildren.Add(childx); |
348 | PhysicallyLinkAChildToRoot(rootx, rootBodyx, childx, childBodyx); | 346 | |
347 | // Since this is taint-time, the body and shape could have changed for the child | ||
348 | PhysicallyLinkAChildToRoot(rootx, rootx.BSBody, childx, childx.BSBody); | ||
349 | }); | 349 | }); |
350 | } | 350 | } |
351 | return; | 351 | return; |
@@ -369,21 +369,19 @@ public class BSLinkset | |||
369 | if (m_children.Remove(child)) | 369 | if (m_children.Remove(child)) |
370 | { | 370 | { |
371 | BSPhysObject rootx = LinksetRoot; // capture the root and body as of now | 371 | BSPhysObject rootx = LinksetRoot; // capture the root and body as of now |
372 | BulletBody rootBodyx = LinksetRoot.BSBody; | ||
373 | BSPhysObject childx = child; | 372 | BSPhysObject childx = child; |
374 | BulletBody childBodyx = child.BSBody; | ||
375 | 373 | ||
376 | DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", | 374 | DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", |
377 | childx.LocalID, | 375 | childx.LocalID, |
378 | rootx.LocalID, rootBodyx.ptr.ToString("X"), | 376 | rootx.LocalID, rootx.BSBody.ptr.ToString("X"), |
379 | childx.LocalID, childBodyx.ptr.ToString("X")); | 377 | childx.LocalID, childx.BSBody.ptr.ToString("X")); |
380 | 378 | ||
381 | PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() | 379 | PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() |
382 | { | 380 | { |
383 | if (m_taintChildren.Contains(childx)) | 381 | if (m_taintChildren.Contains(childx)) |
384 | m_taintChildren.Remove(childx); | 382 | m_taintChildren.Remove(childx); |
385 | 383 | ||
386 | PhysicallyUnlinkAChildFromRoot(rootx, rootBodyx, childx, childBodyx); | 384 | PhysicallyUnlinkAChildFromRoot(rootx, rootx.BSBody, childx, childx.BSBody); |
387 | RecomputeLinksetConstraintVariables(); | 385 | RecomputeLinksetConstraintVariables(); |
388 | }); | 386 | }); |
389 | 387 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index d9b738b..1ac8c59 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | |||
@@ -81,6 +81,10 @@ public abstract class BSPhysObject : PhysicsActor | |||
81 | // Tell the object to clean up. | 81 | // Tell the object to clean up. |
82 | public abstract void Destroy(); | 82 | public abstract void Destroy(); |
83 | 83 | ||
84 | public abstract OMV.Vector3 ForcePosition { get; set; } | ||
85 | |||
86 | public abstract OMV.Quaternion ForceOrientation { get; set; } | ||
87 | |||
84 | #region Collisions | 88 | #region Collisions |
85 | 89 | ||
86 | // Requested number of milliseconds between collision events. Zero means disabled. | 90 | // Requested number of milliseconds between collision events. Zero means disabled. |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index a0e627e..f7b68ba 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -46,19 +46,13 @@ public sealed class BSPrim : BSPhysObject | |||
46 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 46 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
47 | private static readonly string LogHeader = "[BULLETS PRIM]"; | 47 | private static readonly string LogHeader = "[BULLETS PRIM]"; |
48 | 48 | ||
49 | private IMesh _mesh; | ||
50 | private PrimitiveBaseShape _pbs; | 49 | private PrimitiveBaseShape _pbs; |
51 | private ShapeData.PhysicsShapeType _shapeType; | ||
52 | private ulong _meshKey; | ||
53 | private ulong _hullKey; | ||
54 | private List<ConvexResult> _hulls; | ||
55 | 50 | ||
56 | // _size is what the user passed. _scale is what we pass to the physics engine with the mesh. | 51 | // _size is what the user passed. _scale is what we pass to the physics engine with the mesh. |
57 | // Often _scale is unity because the meshmerizer will apply _size when creating the mesh. | 52 | // Often _scale is unity because the meshmerizer will apply _size when creating the mesh. |
58 | private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user | 53 | private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user |
59 | private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer | 54 | private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer |
60 | 55 | ||
61 | private bool _stopped; | ||
62 | private bool _grabbed; | 56 | private bool _grabbed; |
63 | private bool _isSelected; | 57 | private bool _isSelected; |
64 | private bool _isVolumeDetect; | 58 | private bool _isVolumeDetect; |
@@ -109,8 +103,6 @@ public sealed class BSPrim : BSPhysObject | |||
109 | _buoyancy = 1f; | 103 | _buoyancy = 1f; |
110 | _velocity = OMV.Vector3.Zero; | 104 | _velocity = OMV.Vector3.Zero; |
111 | _rotationalVelocity = OMV.Vector3.Zero; | 105 | _rotationalVelocity = OMV.Vector3.Zero; |
112 | _hullKey = 0; | ||
113 | _meshKey = 0; | ||
114 | _pbs = pbs; | 106 | _pbs = pbs; |
115 | _isPhysical = pisPhysical; | 107 | _isPhysical = pisPhysical; |
116 | _isVolumeDetect = false; | 108 | _isVolumeDetect = false; |
@@ -160,8 +152,9 @@ public sealed class BSPrim : BSPhysObject | |||
160 | }); | 152 | }); |
161 | } | 153 | } |
162 | 154 | ||
155 | // No one uses this property. | ||
163 | public override bool Stopped { | 156 | public override bool Stopped { |
164 | get { return _stopped; } | 157 | get { return false; } |
165 | } | 158 | } |
166 | public override OMV.Vector3 Size { | 159 | public override OMV.Vector3 Size { |
167 | get { return _size; } | 160 | get { return _size; } |
@@ -274,6 +267,7 @@ public sealed class BSPrim : BSPhysObject | |||
274 | set { | 267 | set { |
275 | _position = value; | 268 | _position = value; |
276 | // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? | 269 | // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? |
270 | PositionSanityCheck(); | ||
277 | PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() | 271 | PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() |
278 | { | 272 | { |
279 | // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 273 | // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
@@ -281,6 +275,74 @@ public sealed class BSPrim : BSPhysObject | |||
281 | }); | 275 | }); |
282 | } | 276 | } |
283 | } | 277 | } |
278 | public override OMV.Vector3 ForcePosition { | ||
279 | get { | ||
280 | _position = BulletSimAPI.GetPosition2(BSBody.ptr); | ||
281 | return _position; | ||
282 | } | ||
283 | set { | ||
284 | _position = value; | ||
285 | PositionSanityCheck(); | ||
286 | BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); | ||
287 | } | ||
288 | } | ||
289 | |||
290 | // Check that the current position is sane and, if not, modify the position to make it so. | ||
291 | // Check for being below terrain and being out of bounds. | ||
292 | // Returns 'true' of the position was made sane by some action. | ||
293 | private bool PositionSanityCheck() | ||
294 | { | ||
295 | bool ret = false; | ||
296 | |||
297 | // If totally below the ground, move the prim up | ||
298 | // TODO: figure out the right solution for this... only for dynamic objects? | ||
299 | /* | ||
300 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); | ||
301 | if (Position.Z < terrainHeight) | ||
302 | { | ||
303 | DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); | ||
304 | _position.Z = terrainHeight + 2.0f; | ||
305 | ret = true; | ||
306 | } | ||
307 | */ | ||
308 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) | ||
309 | { | ||
310 | float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); | ||
311 | if (Position.Z < waterHeight) | ||
312 | { | ||
313 | _position.Z = waterHeight; | ||
314 | ret = true; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | // TODO: check for out of bounds | ||
319 | return ret; | ||
320 | } | ||
321 | |||
322 | // A version of the sanity check that also makes sure a new position value is | ||
323 | // pushed back to the physics engine. This routine would be used by anyone | ||
324 | // who is not already pushing the value. | ||
325 | private bool PositionSanityCheck2(bool atTaintTime) | ||
326 | { | ||
327 | bool ret = false; | ||
328 | if (PositionSanityCheck()) | ||
329 | { | ||
330 | // The new position value must be pushed into the physics engine but we can't | ||
331 | // just assign to "Position" because of potential call loops. | ||
332 | BSScene.TaintCallback sanityOperation = delegate() | ||
333 | { | ||
334 | DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | ||
335 | BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); | ||
336 | }; | ||
337 | if (atTaintTime) | ||
338 | sanityOperation(); | ||
339 | else | ||
340 | PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation); | ||
341 | |||
342 | ret = true; | ||
343 | } | ||
344 | return ret; | ||
345 | } | ||
284 | 346 | ||
285 | // Return the effective mass of the object. | 347 | // Return the effective mass of the object. |
286 | // If there are multiple items in the linkset, add them together for the root | 348 | // If there are multiple items in the linkset, add them together for the root |
@@ -326,14 +388,15 @@ public sealed class BSPrim : BSPhysObject | |||
326 | } | 388 | } |
327 | set { | 389 | set { |
328 | Vehicle type = (Vehicle)value; | 390 | Vehicle type = (Vehicle)value; |
329 | BSPrim vehiclePrim = this; | 391 | |
392 | // Tell the scene about the vehicle so it will get processing each frame. | ||
393 | PhysicsScene.VehicleInSceneTypeChanged(this, type); | ||
394 | |||
330 | PhysicsScene.TaintedObject("setVehicleType", delegate() | 395 | PhysicsScene.TaintedObject("setVehicleType", delegate() |
331 | { | 396 | { |
332 | // Done at taint time so we're sure the physics engine is not using the variables | 397 | // Done at taint time so we're sure the physics engine is not using the variables |
333 | // Vehicle code changes the parameters for this vehicle type. | 398 | // Vehicle code changes the parameters for this vehicle type. |
334 | _vehicle.ProcessTypeChange(type); | 399 | this._vehicle.ProcessTypeChange(type); |
335 | // Tell the scene about the vehicle so it will get processing each frame. | ||
336 | PhysicsScene.VehicleInSceneTypeChanged(this, type); | ||
337 | }); | 400 | }); |
338 | } | 401 | } |
339 | } | 402 | } |
@@ -371,7 +434,9 @@ public sealed class BSPrim : BSPhysObject | |||
371 | public override void StepVehicle(float timeStep) | 434 | public override void StepVehicle(float timeStep) |
372 | { | 435 | { |
373 | if (IsPhysical) | 436 | if (IsPhysical) |
437 | { | ||
374 | _vehicle.Step(timeStep); | 438 | _vehicle.Step(timeStep); |
439 | } | ||
375 | } | 440 | } |
376 | 441 | ||
377 | // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more | 442 | // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more |
@@ -435,6 +500,20 @@ public sealed class BSPrim : BSPhysObject | |||
435 | }); | 500 | }); |
436 | } | 501 | } |
437 | } | 502 | } |
503 | // Go directly to Bullet to get/set the value. | ||
504 | public override OMV.Quaternion ForceOrientation | ||
505 | { | ||
506 | get | ||
507 | { | ||
508 | _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr); | ||
509 | return _orientation; | ||
510 | } | ||
511 | set | ||
512 | { | ||
513 | _orientation = value; | ||
514 | BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); | ||
515 | } | ||
516 | } | ||
438 | public override int PhysicsActorType { | 517 | public override int PhysicsActorType { |
439 | get { return _physicsActorType; } | 518 | get { return _physicsActorType; } |
440 | set { _physicsActorType = value; } | 519 | set { _physicsActorType = value; } |
@@ -488,11 +567,10 @@ public sealed class BSPrim : BSPhysObject | |||
488 | // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). | 567 | // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). |
489 | BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); | 568 | BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); |
490 | 569 | ||
491 | |||
492 | // Set up the object physicalness (does gravity and collisions move this object) | 570 | // Set up the object physicalness (does gravity and collisions move this object) |
493 | MakeDynamic(IsStatic); | 571 | MakeDynamic(IsStatic); |
494 | 572 | ||
495 | // Do any vehicle stuff | 573 | // Update vehicle specific parameters |
496 | _vehicle.Refresh(); | 574 | _vehicle.Refresh(); |
497 | 575 | ||
498 | // Arrange for collision events if the simulator wants them | 576 | // Arrange for collision events if the simulator wants them |
@@ -563,7 +641,6 @@ public sealed class BSPrim : BSPhysObject | |||
563 | // A dynamic object has mass | 641 | // A dynamic object has mass |
564 | IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); | 642 | IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); |
565 | OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass); | 643 | OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass); |
566 | // OMV.Vector3 inertia = OMV.Vector3.Zero; | ||
567 | BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia); | 644 | BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia); |
568 | BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); | 645 | BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); |
569 | 646 | ||
@@ -573,7 +650,7 @@ public sealed class BSPrim : BSPhysObject | |||
573 | BulletSimAPI.SetSleepingThresholds2(BSBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); | 650 | BulletSimAPI.SetSleepingThresholds2(BSBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); |
574 | BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); | 651 | BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); |
575 | 652 | ||
576 | // There can be special things needed for implementing linksets. | 653 | // There might be special things needed for implementing linksets. |
577 | Linkset.MakeDynamic(this); | 654 | Linkset.MakeDynamic(this); |
578 | 655 | ||
579 | // Force activation of the object so Bullet will act on it. | 656 | // Force activation of the object so Bullet will act on it. |
@@ -663,7 +740,16 @@ public sealed class BSPrim : BSPhysObject | |||
663 | } | 740 | } |
664 | } | 741 | } |
665 | public override bool FloatOnWater { | 742 | public override bool FloatOnWater { |
666 | set { _floatOnWater = value; } | 743 | set { |
744 | _floatOnWater = value; | ||
745 | PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() | ||
746 | { | ||
747 | if (_floatOnWater) | ||
748 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); | ||
749 | else | ||
750 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); | ||
751 | }); | ||
752 | } | ||
667 | } | 753 | } |
668 | public override OMV.Vector3 RotationalVelocity { | 754 | public override OMV.Vector3 RotationalVelocity { |
669 | get { | 755 | get { |
@@ -1082,15 +1168,15 @@ public sealed class BSPrim : BSPhysObject | |||
1082 | public void FillShapeInfo(out ShapeData shape) | 1168 | public void FillShapeInfo(out ShapeData shape) |
1083 | { | 1169 | { |
1084 | shape.ID = LocalID; | 1170 | shape.ID = LocalID; |
1085 | shape.Type = _shapeType; | 1171 | shape.Type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; |
1086 | shape.Position = _position; | 1172 | shape.Position = _position; |
1087 | shape.Rotation = _orientation; | 1173 | shape.Rotation = _orientation; |
1088 | shape.Velocity = _velocity; | 1174 | shape.Velocity = _velocity; |
1089 | shape.Scale = _scale; | 1175 | shape.Scale = _scale; |
1090 | shape.Mass = _isPhysical ? _mass : 0f; | 1176 | shape.Mass = _isPhysical ? _mass : 0f; |
1091 | shape.Buoyancy = _buoyancy; | 1177 | shape.Buoyancy = _buoyancy; |
1092 | shape.HullKey = _hullKey; | 1178 | shape.HullKey = 0; |
1093 | shape.MeshKey = _meshKey; | 1179 | shape.MeshKey = 0; |
1094 | shape.Friction = _friction; | 1180 | shape.Friction = _friction; |
1095 | shape.Restitution = _restitution; | 1181 | shape.Restitution = _restitution; |
1096 | shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; | 1182 | shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; |
@@ -1112,7 +1198,8 @@ public sealed class BSPrim : BSPhysObject | |||
1112 | 1198 | ||
1113 | // Create the correct physical representation for this type of object. | 1199 | // Create the correct physical representation for this type of object. |
1114 | // Updates BSBody and BSShape with the new information. | 1200 | // Updates BSBody and BSShape with the new information. |
1115 | PhysicsScene.Shapes.GetBodyAndShape(forceRebuild, PhysicsScene.World, this, shapeData, _pbs, | 1201 | // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. |
1202 | PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, _pbs, | ||
1116 | null, delegate(BulletBody dBody) | 1203 | null, delegate(BulletBody dBody) |
1117 | { | 1204 | { |
1118 | // Called if the current prim body is about to be destroyed. | 1205 | // Called if the current prim body is about to be destroyed. |
@@ -1205,6 +1292,8 @@ public sealed class BSPrim : BSPhysObject | |||
1205 | _acceleration = entprop.Acceleration; | 1292 | _acceleration = entprop.Acceleration; |
1206 | _rotationalVelocity = entprop.RotationalVelocity; | 1293 | _rotationalVelocity = entprop.RotationalVelocity; |
1207 | 1294 | ||
1295 | PositionSanityCheck2(true); | ||
1296 | |||
1208 | DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | 1297 | DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", |
1209 | LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); | 1298 | LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); |
1210 | 1299 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 0cf8c91..aaed7de 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -493,6 +493,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
493 | // step the physical world one interval | 493 | // step the physical world one interval |
494 | m_simulationStep++; | 494 | m_simulationStep++; |
495 | int numSubSteps = 0; | 495 | int numSubSteps = 0; |
496 | |||
497 | // Sometimes needed for debugging to find out what happened before the step | ||
498 | // PhysicsLogging.Flush(); | ||
499 | |||
496 | try | 500 | try |
497 | { | 501 | { |
498 | if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); | 502 | if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); |
@@ -536,7 +540,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
536 | } | 540 | } |
537 | 541 | ||
538 | // This is a kludge to get avatar movement updates. | 542 | // This is a kludge to get avatar movement updates. |
539 | // ODE sends collisions for avatars even if there are have been no collisions. This updates | 543 | // the simulator expects collisions for avatars even if there are have been no collisions. This updates |
540 | // avatar animations and stuff. | 544 | // avatar animations and stuff. |
541 | // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. | 545 | // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. |
542 | foreach (BSPhysObject bsp in m_avatars) | 546 | foreach (BSPhysObject bsp in m_avatars) |
@@ -556,7 +560,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
556 | } | 560 | } |
557 | 561 | ||
558 | // Objects that are done colliding are removed from the ObjectsWithCollisions list. | 562 | // Objects that are done colliding are removed from the ObjectsWithCollisions list. |
559 | // This can't be done by SendCollisions because it is inside an iteration of ObjectWithCollisions. | 563 | // Not done above because it is inside an iteration of ObjectWithCollisions. |
560 | if (ObjectsWithNoMoreCollisions.Count > 0) | 564 | if (ObjectsWithNoMoreCollisions.Count > 0) |
561 | { | 565 | { |
562 | foreach (BSPhysObject po in ObjectsWithNoMoreCollisions) | 566 | foreach (BSPhysObject po in ObjectsWithNoMoreCollisions) |
@@ -726,13 +730,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
726 | 730 | ||
727 | public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) | 731 | public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) |
728 | { | 732 | { |
729 | if (newType == Vehicle.TYPE_NONE) | 733 | RemoveVehiclePrim(vehic); |
730 | { | 734 | if (newType != Vehicle.TYPE_NONE) |
731 | RemoveVehiclePrim(vehic); | ||
732 | } | ||
733 | else | ||
734 | { | 735 | { |
735 | // make it so the scene will call us each tick to do vehicle things | 736 | // make it so the scene will call us each tick to do vehicle things |
736 | AddVehiclePrim(vehic); | 737 | AddVehiclePrim(vehic); |
737 | } | 738 | } |
738 | } | 739 | } |
@@ -764,7 +765,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
764 | } | 765 | } |
765 | 766 | ||
766 | // Some prims have extra vehicle actions | 767 | // Some prims have extra vehicle actions |
767 | // no locking because only called when physics engine is not busy | 768 | // Called at taint time! |
768 | private void ProcessVehicles(float timeStep) | 769 | private void ProcessVehicles(float timeStep) |
769 | { | 770 | { |
770 | foreach (BSPhysObject pobj in m_vehicles) | 771 | foreach (BSPhysObject pobj in m_vehicles) |
@@ -1008,12 +1009,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1008 | 1009 | ||
1009 | 1010 | ||
1010 | new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", | 1011 | new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", |
1011 | 0f, // zero to disable | 1012 | 0f, |
1012 | (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, | 1013 | (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, |
1013 | (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, | 1014 | (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, |
1014 | (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), | 1015 | (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), |
1015 | new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", | 1016 | new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", |
1016 | 0f, // zero to disable | 1017 | 0f, |
1017 | (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); }, | 1018 | (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); }, |
1018 | (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; }, | 1019 | (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; }, |
1019 | (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ), | 1020 | (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ), |
@@ -1028,7 +1029,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1028 | (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; }, | 1029 | (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; }, |
1029 | (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ), | 1030 | (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ), |
1030 | new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", | 1031 | new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", |
1031 | ConfigurationParameters.numericFalse, | 1032 | ConfigurationParameters.numericTrue, |
1032 | (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | 1033 | (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, |
1033 | (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, | 1034 | (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, |
1034 | (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), | 1035 | (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), |
@@ -1152,7 +1153,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1152 | { | 1153 | { |
1153 | if (SettableParameters.Length < ParameterDefinitions.Length) | 1154 | if (SettableParameters.Length < ParameterDefinitions.Length) |
1154 | { | 1155 | { |
1155 | |||
1156 | List<PhysParameterEntry> entries = new List<PhysParameterEntry>(); | 1156 | List<PhysParameterEntry> entries = new List<PhysParameterEntry>(); |
1157 | for (int ii = 0; ii < ParameterDefinitions.Length; ii++) | 1157 | for (int ii = 0; ii < ParameterDefinitions.Length; ii++) |
1158 | { | 1158 | { |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index dee6243..399a133 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | |||
@@ -36,7 +36,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
36 | { | 36 | { |
37 | public class BSShapeCollection : IDisposable | 37 | public class BSShapeCollection : IDisposable |
38 | { | 38 | { |
39 | private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; | 39 | // private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; |
40 | 40 | ||
41 | protected BSScene PhysicsScene { get; set; } | 41 | protected BSScene PhysicsScene { get; set; } |
42 | 42 | ||
@@ -108,7 +108,8 @@ public class BSShapeCollection : IDisposable | |||
108 | // If we had to select a new shape geometry for the object, | 108 | // If we had to select a new shape geometry for the object, |
109 | // rebuild the body around it. | 109 | // rebuild the body around it. |
110 | // Updates prim.BSBody with information/pointers to requested body | 110 | // Updates prim.BSBody with information/pointers to requested body |
111 | bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData, bodyCallback); | 111 | bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, |
112 | prim.BSShape, shapeData, bodyCallback); | ||
112 | ret = newGeom || newBody; | 113 | ret = newGeom || newBody; |
113 | } | 114 | } |
114 | DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}", | 115 | DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}", |
@@ -140,7 +141,7 @@ public class BSShapeCollection : IDisposable | |||
140 | bodyDesc.lastReferenced = System.DateTime.Now; | 141 | bodyDesc.lastReferenced = System.DateTime.Now; |
141 | Bodies[body.ID] = bodyDesc; | 142 | Bodies[body.ID] = bodyDesc; |
142 | } | 143 | } |
143 | } | 144 | } |
144 | 145 | ||
145 | // Release the usage of a body. | 146 | // Release the usage of a body. |
146 | // Called when releasing use of a BSBody. BSShape is handled separately. | 147 | // Called when releasing use of a BSBody. BSShape is handled separately. |
@@ -167,7 +168,7 @@ public class BSShapeCollection : IDisposable | |||
167 | { | 168 | { |
168 | DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", | 169 | DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", |
169 | body.ID, body.ptr.ToString("X")); | 170 | body.ID, body.ptr.ToString("X")); |
170 | // If the caller needs to know, pass the event up. | 171 | // If the caller needs to know the old body is going away, pass the event up. |
171 | if (bodyCallback != null) bodyCallback(body); | 172 | if (bodyCallback != null) bodyCallback(body); |
172 | 173 | ||
173 | // Zero any reference to the shape so it is not freed when the body is deleted. | 174 | // Zero any reference to the shape so it is not freed when the body is deleted. |
@@ -448,7 +449,8 @@ public class BSShapeCollection : IDisposable | |||
448 | ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); | 449 | ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); |
449 | 450 | ||
450 | // if this new shape is the same as last time, don't recreate the mesh | 451 | // if this new shape is the same as last time, don't recreate the mesh |
451 | if (prim.BSShape.shapeKey == newMeshKey) return false; | 452 | if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) |
453 | return false; | ||
452 | 454 | ||
453 | DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", | 455 | DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", |
454 | prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); | 456 | prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 1125d7e..a43880d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | |||
@@ -71,7 +71,7 @@ public struct BulletBody | |||
71 | buff.Append(ID.ToString()); | 71 | buff.Append(ID.ToString()); |
72 | buff.Append(",p="); | 72 | buff.Append(",p="); |
73 | buff.Append(ptr.ToString("X")); | 73 | buff.Append(ptr.ToString("X")); |
74 | if (collisionFilter != 0 && collisionMask != 0) | 74 | if (collisionFilter != 0 || collisionMask != 0) |
75 | { | 75 | { |
76 | buff.Append(",f="); | 76 | buff.Append(",f="); |
77 | buff.Append(collisionFilter.ToString("X")); | 77 | buff.Append(collisionFilter.ToString("X")); |
@@ -344,10 +344,7 @@ public enum CollisionFlags : uint | |||
344 | CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, | 344 | CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, |
345 | // Following used by BulletSim to control collisions | 345 | // Following used by BulletSim to control collisions |
346 | BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, | 346 | BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, |
347 | // BS_VOLUME_DETECT_OBJECT = 1 << 11, | 347 | BS_FLOATS_ON_WATER = 1 << 11, |
348 | // BS_PHANTOM_OBJECT = 1 << 12, | ||
349 | // BS_PHYSICAL_OBJECT = 1 << 13, | ||
350 | // BS_TERRAIN_OBJECT = 1 << 14, | ||
351 | BS_NONE = 0, | 348 | BS_NONE = 0, |
352 | BS_ALL = 0xFFFFFFFF, | 349 | BS_ALL = 0xFFFFFFFF, |
353 | 350 | ||
@@ -356,9 +353,6 @@ public enum CollisionFlags : uint | |||
356 | BS_ACTIVE = CF_STATIC_OBJECT | 353 | BS_ACTIVE = CF_STATIC_OBJECT |
357 | | CF_KINEMATIC_OBJECT | 354 | | CF_KINEMATIC_OBJECT |
358 | | CF_NO_CONTACT_RESPONSE | 355 | | CF_NO_CONTACT_RESPONSE |
359 | // | BS_VOLUME_DETECT_OBJECT | ||
360 | // | BS_PHANTOM_OBJECT | ||
361 | // | BS_PHYSICAL_OBJECT, | ||
362 | }; | 356 | }; |
363 | 357 | ||
364 | // Values for collisions groups and masks | 358 | // Values for collisions groups and masks |
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 0716214..e7b3b2b 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; |
@@ -2395,15 +2404,15 @@ Console.WriteLine(" JointCreateFixed"); | |||
2395 | { | 2404 | { |
2396 | get | 2405 | get |
2397 | { | 2406 | { |
2398 | // Averate previous velocity with the new one so | 2407 | // Average previous velocity with the new one so |
2399 | // client object interpolation works a 'little' better | 2408 | // client object interpolation works a 'little' better |
2400 | if (_zeroFlag) | 2409 | if (_zeroFlag) |
2401 | return Vector3.Zero; | 2410 | return Vector3.Zero; |
2402 | 2411 | ||
2403 | Vector3 returnVelocity = Vector3.Zero; | 2412 | Vector3 returnVelocity = Vector3.Zero; |
2404 | returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2; | 2413 | returnVelocity.X = (m_lastVelocity.X + _velocity.X) * 0.5f; // 0.5f is mathematically equiv to '/ 2' |
2405 | returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2; | 2414 | returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y) * 0.5f; |
2406 | returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2; | 2415 | returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z) * 0.5f; |
2407 | return returnVelocity; | 2416 | return returnVelocity; |
2408 | } | 2417 | } |
2409 | set | 2418 | set |
@@ -2600,6 +2609,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
2600 | { | 2609 | { |
2601 | Vector3 pv = Vector3.Zero; | 2610 | Vector3 pv = Vector3.Zero; |
2602 | bool lastZeroFlag = _zeroFlag; | 2611 | bool lastZeroFlag = _zeroFlag; |
2612 | float m_minvelocity = 0; | ||
2603 | if (Body != (IntPtr)0) // FIXME -> or if it is a joint | 2613 | if (Body != (IntPtr)0) // FIXME -> or if it is a joint |
2604 | { | 2614 | { |
2605 | d.Vector3 vec = d.BodyGetPosition(Body); | 2615 | d.Vector3 vec = d.BodyGetPosition(Body); |
@@ -2752,8 +2762,21 @@ Console.WriteLine(" JointCreateFixed"); | |||
2752 | _acceleration = ((_velocity - m_lastVelocity) / 0.1f); | 2762 | _acceleration = ((_velocity - m_lastVelocity) / 0.1f); |
2753 | _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f); | 2763 | _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f); |
2754 | //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString()); | 2764 | //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString()); |
2765 | |||
2766 | // Note here that linearvelocity is affecting angular velocity... so I'm guessing this is a vehicle specific thing... | ||
2767 | // it does make sense to do this for tiny little instabilities with physical prim, however 0.5m/frame is fairly large. | ||
2768 | // reducing this to 0.02m/frame seems to help the angular rubberbanding quite a bit, however, to make sure it doesn't affect elevators and vehicles | ||
2769 | // adding these logical exclusion situations to maintain this where I think it was intended to be. | ||
2770 | if (m_throttleUpdates || m_usePID || (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) || (Amotor != IntPtr.Zero)) | ||
2771 | { | ||
2772 | m_minvelocity = 0.5f; | ||
2773 | } | ||
2774 | else | ||
2775 | { | ||
2776 | m_minvelocity = 0.02f; | ||
2777 | } | ||
2755 | 2778 | ||
2756 | if (_velocity.ApproxEquals(pv, 0.5f)) | 2779 | if (_velocity.ApproxEquals(pv, m_minvelocity)) |
2757 | { | 2780 | { |
2758 | m_rotationalVelocity = pv; | 2781 | m_rotationalVelocity = pv; |
2759 | } | 2782 | } |
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 ... |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 52d96bc..7fa6f05 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -4006,7 +4006,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4006 | { | 4006 | { |
4007 | m_host.AddScriptLPS(1); | 4007 | m_host.AddScriptLPS(1); |
4008 | Vector3 av3 = Util.Clip(color, 0.0f, 1.0f); | 4008 | Vector3 av3 = Util.Clip(color, 0.0f, 1.0f); |
4009 | m_host.SetText(text.Length > 254 ? text.Remove(254) : text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); | 4009 | if (text.Length > 254) |
4010 | text = text.Remove(254); | ||
4011 | |||
4012 | byte[] data; | ||
4013 | do | ||
4014 | { | ||
4015 | data = Util.UTF8.GetBytes(text); | ||
4016 | if (data.Length > 254) | ||
4017 | text = text.Substring(0, text.Length - 1); | ||
4018 | } while (data.Length > 254); | ||
4019 | |||
4020 | m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); | ||
4010 | //m_host.ParentGroup.HasGroupChanged = true; | 4021 | //m_host.ParentGroup.HasGroupChanged = true; |
4011 | //m_host.ParentGroup.ScheduleGroupForFullUpdate(); | 4022 | //m_host.ParentGroup.ScheduleGroupForFullUpdate(); |
4012 | } | 4023 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 8b73cd9..31be450 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | |||
@@ -3538,7 +3538,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3538 | 3538 | ||
3539 | return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); | 3539 | return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); |
3540 | } | 3540 | } |
3541 | 3541 | ||
3542 | /// <summary> | 3542 | /// <summary> |
3543 | /// Sets the response type for an HTTP request/response | 3543 | /// Sets the response type for an HTTP request/response |
3544 | /// </summary> | 3544 | /// </summary> |
@@ -3549,6 +3549,91 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3549 | if (m_UrlModule != null) | 3549 | if (m_UrlModule != null) |
3550 | m_UrlModule.HttpContentType(new UUID(id),type); | 3550 | m_UrlModule.HttpContentType(new UUID(id),type); |
3551 | } | 3551 | } |
3552 | 3552 | /// Shout an error if the object owner did not grant the script the specified permissions. | |
3553 | } | 3553 | /// </summary> |
3554 | /// <param name="perms"></param> | ||
3555 | /// <returns>boolean indicating whether an error was shouted.</returns> | ||
3556 | protected bool ShoutErrorOnLackingOwnerPerms(int perms, string errorPrefix) | ||
3557 | { | ||
3558 | CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment"); | ||
3559 | m_host.AddScriptLPS(1); | ||
3560 | bool fail = false; | ||
3561 | if (m_item.PermsGranter != m_host.OwnerID) | ||
3562 | { | ||
3563 | fail = true; | ||
3564 | OSSLShoutError(string.Format("{0}. Permissions not granted to owner.", errorPrefix)); | ||
3565 | } | ||
3566 | else if ((m_item.PermsMask & perms) == 0) | ||
3567 | { | ||
3568 | fail = true; | ||
3569 | OSSLShoutError(string.Format("{0}. Permissions not granted.", errorPrefix)); | ||
3570 | } | ||
3571 | |||
3572 | return fail; | ||
3573 | } | ||
3574 | |||
3575 | protected void DropAttachment(bool checkPerms) | ||
3576 | { | ||
3577 | if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment")) | ||
3578 | { | ||
3579 | return; | ||
3580 | } | ||
3581 | |||
3582 | IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; | ||
3583 | ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID); | ||
3584 | |||
3585 | if (attachmentsModule != null && sp != null) | ||
3586 | { | ||
3587 | attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId); | ||
3588 | } | ||
3589 | } | ||
3590 | |||
3591 | protected void DropAttachmentAt(bool checkPerms, LSL_Vector pos, LSL_Rotation rot) | ||
3592 | { | ||
3593 | if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment")) | ||
3594 | { | ||
3595 | return; | ||
3596 | } | ||
3597 | |||
3598 | IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; | ||
3599 | ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID); | ||
3600 | |||
3601 | if (attachmentsModule != null && sp != null) | ||
3602 | { | ||
3603 | attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId, pos, rot); | ||
3604 | } | ||
3605 | } | ||
3606 | |||
3607 | public void osDropAttachment() | ||
3608 | { | ||
3609 | CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment"); | ||
3610 | m_host.AddScriptLPS(1); | ||
3611 | |||
3612 | DropAttachment(true); | ||
3613 | } | ||
3614 | |||
3615 | public void osForceDropAttachment() | ||
3616 | { | ||
3617 | CheckThreatLevel(ThreatLevel.High, "osForceDropAttachment"); | ||
3618 | m_host.AddScriptLPS(1); | ||
3619 | |||
3620 | DropAttachment(false); | ||
3621 | } | ||
3622 | |||
3623 | public void osDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) | ||
3624 | { | ||
3625 | CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachmentAt"); | ||
3626 | m_host.AddScriptLPS(1); | ||
3627 | |||
3628 | DropAttachmentAt(true, pos, rot); | ||
3629 | } | ||
3630 | |||
3631 | public void osForceDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) | ||
3632 | { | ||
3633 | CheckThreatLevel(ThreatLevel.High, "osForceDropAttachmentAt"); | ||
3634 | m_host.AddScriptLPS(1); | ||
3635 | |||
3636 | DropAttachmentAt(false, pos, rot); | ||
3637 | } | ||
3638 | } | ||
3554 | } \ No newline at end of file | 3639 | } \ No newline at end of file |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 3985e66..93188c9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | |||
@@ -394,5 +394,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | |||
394 | /// </summary> | 394 | /// </summary> |
395 | /// <returns></returns> | 395 | /// <returns></returns> |
396 | void osSetContentType(LSL_Key id, string type); | 396 | void osSetContentType(LSL_Key id, string type); |
397 | |||
398 | /// <summary> | ||
399 | /// Attempts to drop an attachment to the ground | ||
400 | /// </summary> | ||
401 | void osDropAttachment(); | ||
402 | |||
403 | /// <summary> | ||
404 | /// Attempts to drop an attachment to the ground while bypassing the script permissions | ||
405 | /// </summary> | ||
406 | void osForceDropAttachment(); | ||
407 | |||
408 | /// <summary> | ||
409 | /// Attempts to drop an attachment at the specified coordinates. | ||
410 | /// </summary> | ||
411 | /// <param name="pos"></param> | ||
412 | /// <param name="rot"></param> | ||
413 | void osDropAttachmentAt(vector pos, rotation rot); | ||
414 | |||
415 | /// <summary> | ||
416 | /// Attempts to drop an attachment at the specified coordinates while bypassing the script permissions | ||
417 | /// </summary> | ||
418 | /// <param name="pos"></param> | ||
419 | /// <param name="rot"></param> | ||
420 | void osForceDropAttachmentAt(vector pos, rotation rot); | ||
397 | } | 421 | } |
398 | } | 422 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 52ca3da..dee1b28 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | |||
@@ -972,5 +972,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
972 | { | 972 | { |
973 | m_OSSL_Functions.osSetContentType(id,type); | 973 | m_OSSL_Functions.osSetContentType(id,type); |
974 | } | 974 | } |
975 | |||
976 | public void osDropAttachment() | ||
977 | { | ||
978 | m_OSSL_Functions.osDropAttachment(); | ||
979 | } | ||
980 | |||
981 | public void osForceDropAttachment() | ||
982 | { | ||
983 | m_OSSL_Functions.osForceDropAttachment(); | ||
984 | } | ||
985 | |||
986 | public void osDropAttachmentAt(vector pos, rotation rot) | ||
987 | { | ||
988 | m_OSSL_Functions.osDropAttachmentAt(pos, rot); | ||
989 | } | ||
990 | |||
991 | public void osForceDropAttachmentAt(vector pos, rotation rot) | ||
992 | { | ||
993 | m_OSSL_Functions.osForceDropAttachmentAt(pos, rot); | ||
994 | } | ||
975 | } | 995 | } |
976 | } | 996 | } |
diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs index cee10df..9405075 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs | |||
@@ -96,9 +96,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
96 | if (part == null) | 96 | if (part == null) |
97 | return; | 97 | return; |
98 | 98 | ||
99 | if ((part.ScriptEvents & scriptEvents.money) == 0) | ||
100 | part = part.ParentGroup.RootPart; | ||
101 | |||
99 | m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount); | 102 | m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount); |
100 | 103 | ||
101 | part = part.ParentGroup.RootPart; | 104 | // part = part.ParentGroup.RootPart; |
102 | money(part.LocalId, agentID, amount); | 105 | money(part.LocalId, agentID, amount); |
103 | } | 106 | } |
104 | 107 | ||
diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs index 086b5ad..2b2f11f 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs | |||
@@ -47,7 +47,8 @@ namespace OpenSim.Services.Connectors | |||
47 | 47 | ||
48 | private string m_ServerURI = String.Empty; | 48 | private string m_ServerURI = String.Empty; |
49 | private IImprovedAssetCache m_Cache = null; | 49 | private IImprovedAssetCache m_Cache = null; |
50 | 50 | private int m_maxAssetRequestConcurrency = 30; | |
51 | |||
51 | private delegate void AssetRetrievedEx(AssetBase asset); | 52 | private delegate void AssetRetrievedEx(AssetBase asset); |
52 | 53 | ||
53 | // Keeps track of concurrent requests for the same asset, so that it's only loaded once. | 54 | // Keeps track of concurrent requests for the same asset, so that it's only loaded once. |
@@ -71,6 +72,10 @@ namespace OpenSim.Services.Connectors | |||
71 | 72 | ||
72 | public virtual void Initialise(IConfigSource source) | 73 | public virtual void Initialise(IConfigSource source) |
73 | { | 74 | { |
75 | IConfig netconfig = source.Configs["Network"]; | ||
76 | if (netconfig != null) | ||
77 | m_maxAssetRequestConcurrency = netconfig.GetInt("MaxRequestConcurrency",m_maxAssetRequestConcurrency); | ||
78 | |||
74 | IConfig assetConfig = source.Configs["AssetService"]; | 79 | IConfig assetConfig = source.Configs["AssetService"]; |
75 | if (assetConfig == null) | 80 | if (assetConfig == null) |
76 | { | 81 | { |
@@ -108,7 +113,7 @@ namespace OpenSim.Services.Connectors | |||
108 | if (asset == null) | 113 | if (asset == null) |
109 | { | 114 | { |
110 | asset = SynchronousRestObjectRequester. | 115 | asset = SynchronousRestObjectRequester. |
111 | MakeRequest<int, AssetBase>("GET", uri, 0, 30); | 116 | MakeRequest<int, AssetBase>("GET", uri, 0, m_maxAssetRequestConcurrency); |
112 | 117 | ||
113 | if (m_Cache != null) | 118 | if (m_Cache != null) |
114 | m_Cache.Cache(asset); | 119 | m_Cache.Cache(asset); |
@@ -221,7 +226,7 @@ namespace OpenSim.Services.Connectors | |||
221 | m_AssetHandlers.Remove(id); | 226 | m_AssetHandlers.Remove(id); |
222 | } | 227 | } |
223 | handlers.Invoke(a); | 228 | handlers.Invoke(a); |
224 | }, 30); | 229 | }, m_maxAssetRequestConcurrency); |
225 | 230 | ||
226 | success = true; | 231 | success = true; |
227 | } | 232 | } |
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 495dc52..59fb559 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs | |||
@@ -293,7 +293,7 @@ namespace OpenSim.Services.LLLoginService | |||
293 | { | 293 | { |
294 | m_log.InfoFormat( | 294 | m_log.InfoFormat( |
295 | "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: user level is {2} but minimum login level is {3}", | 295 | "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: user level is {2} but minimum login level is {3}", |
296 | firstName, lastName, m_MinLoginLevel, account.UserLevel); | 296 | firstName, lastName, account.UserLevel, m_MinLoginLevel); |
297 | return LLFailedLoginResponse.LoginBlockedProblem; | 297 | return LLFailedLoginResponse.LoginBlockedProblem; |
298 | } | 298 | } |
299 | 299 | ||
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 6e6a089..677ac74 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini | |||
@@ -427,6 +427,10 @@ | |||
427 | ; " (Mozilla Compatible)" to the text where there are problems with a web server | 427 | ; " (Mozilla Compatible)" to the text where there are problems with a web server |
428 | ;user_agent = "OpenSim LSL (Mozilla Compatible)" | 428 | ;user_agent = "OpenSim LSL (Mozilla Compatible)" |
429 | 429 | ||
430 | ; OpenSim can send multiple simultaneous requests for services such as asset | ||
431 | ; retrieval. However, some versions of mono appear to hang when there are too | ||
432 | ; many simultaneous requests, default is 30 and is currently applied only to assets | ||
433 | ;MaxRequestConcurrency = 30 | ||
430 | 434 | ||
431 | [XMLRPC] | 435 | [XMLRPC] |
432 | ; ## | 436 | ; ## |
diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll index da6e31c..1fd0a60 100755 --- a/bin/lib32/BulletSim.dll +++ b/bin/lib32/BulletSim.dll | |||
Binary files differ | |||
diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so index 9503cdb..3b42048 100755 --- a/bin/lib32/libBulletSim.so +++ b/bin/lib32/libBulletSim.so | |||
Binary files differ | |||
diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll index 1782c8e..bfaabde 100755 --- a/bin/lib64/BulletSim.dll +++ b/bin/lib64/BulletSim.dll | |||
Binary files differ | |||
diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so index 06e6ce2..54ddad9 100755 --- a/bin/lib64/libBulletSim.so +++ b/bin/lib64/libBulletSim.so | |||
Binary files differ | |||