aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs35
-rw-r--r--OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs508
-rw-r--r--OpenSim/Framework/PrimitiveBaseShape.cs21
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs2
-rw-r--r--OpenSim/Framework/Tests/MundaneFrameworkTests.cs8
-rw-r--r--OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs5
-rw-r--r--OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/EntityManager.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs15
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs287
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs376
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs7
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs61
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs1
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt87
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs25
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs51
27 files changed, 1133 insertions, 416 deletions
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index 6437d0b..822c50d 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -225,6 +225,11 @@ namespace OpenSim.Capabilities.Handlers
225 } 225 }
226 else 226 else
227 { 227 {
228 // Handle the case where no second range value was given. This is equivalent to requesting
229 // the rest of the entity.
230 if (end == -1)
231 end = int.MaxValue;
232
228 end = Utils.Clamp(end, 0, texture.Data.Length - 1); 233 end = Utils.Clamp(end, 0, texture.Data.Length - 1);
229 start = Utils.Clamp(start, 0, end); 234 start = Utils.Clamp(start, 0, end);
230 int len = end - start + 1; 235 int len = end - start + 1;
@@ -283,15 +288,43 @@ namespace OpenSim.Capabilities.Handlers
283// texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length); 288// texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
284 } 289 }
285 290
291 /// <summary>
292 /// Parse a range header.
293 /// </summary>
294 /// <remarks>
295 /// As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html,
296 /// this obeys range headers with two values (e.g. 533-4165) and no second value (e.g. 533-).
297 /// Where there is no value, -1 is returned.
298 /// FIXME: Need to cover the case where only a second value is specified (e.g. -4165), probably by returning -1
299 /// for start.</remarks>
300 /// <returns></returns>
301 /// <param name='header'></param>
302 /// <param name='start'>Start of the range. Undefined if this was not a number.</param>
303 /// <param name='end'>End of the range. Will be -1 if no end specified. Undefined if there was a raw string but this was not a number.</param>
286 private bool TryParseRange(string header, out int start, out int end) 304 private bool TryParseRange(string header, out int start, out int end)
287 { 305 {
306 start = end = 0;
307
288 if (header.StartsWith("bytes=")) 308 if (header.StartsWith("bytes="))
289 { 309 {
290 string[] rangeValues = header.Substring(6).Split('-'); 310 string[] rangeValues = header.Substring(6).Split('-');
311
291 if (rangeValues.Length == 2) 312 if (rangeValues.Length == 2)
292 { 313 {
293 if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end)) 314 if (!Int32.TryParse(rangeValues[0], out start))
315 return false;
316
317 string rawEnd = rangeValues[1];
318
319 if (rawEnd == "")
320 {
321 end = -1;
322 return true;
323 }
324 else if (Int32.TryParse(rawEnd, out end))
325 {
294 return true; 326 return true;
327 }
295 } 328 }
296 } 329 }
297 330
diff --git a/OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs b/OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs
new file mode 100644
index 0000000..9056548
--- /dev/null
+++ b/OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs
@@ -0,0 +1,508 @@
1/*
2 * Copyright (c) 2008, openmetaverse.org, http://opensimulator.org/
3 * All rights reserved.
4 *
5 * - Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * - Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * - Neither the name of the openmetaverse.org nor the names
11 * of its contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26
27using System;
28using System.Threading;
29using System.Collections.Generic;
30
31namespace OpenSim.Framework
32{
33 /// <summary>
34 /// A double dictionary that is thread abort safe.
35 /// </summary>
36 /// <remarks>
37 /// This adapts OpenMetaverse.DoubleDictionary to be thread-abort safe by acquiring ReaderWriterLockSlim within
38 /// a finally section (which can't be interrupted by Thread.Abort()).
39 /// </remarks>
40 public class DoubleDictionaryThreadAbortSafe<TKey1, TKey2, TValue>
41 {
42 Dictionary<TKey1, TValue> Dictionary1;
43 Dictionary<TKey2, TValue> Dictionary2;
44 ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
45
46 public DoubleDictionaryThreadAbortSafe()
47 {
48 Dictionary1 = new Dictionary<TKey1,TValue>();
49 Dictionary2 = new Dictionary<TKey2,TValue>();
50 }
51
52 public DoubleDictionaryThreadAbortSafe(int capacity)
53 {
54 Dictionary1 = new Dictionary<TKey1, TValue>(capacity);
55 Dictionary2 = new Dictionary<TKey2, TValue>(capacity);
56 }
57
58 public void Add(TKey1 key1, TKey2 key2, TValue value)
59 {
60 bool gotLock = false;
61
62 try
63 {
64 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
65 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
66 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
67 try {}
68 finally
69 {
70 rwLock.EnterWriteLock();
71 gotLock = true;
72 }
73
74 if (Dictionary1.ContainsKey(key1))
75 {
76 if (!Dictionary2.ContainsKey(key2))
77 throw new ArgumentException("key1 exists in the dictionary but not key2");
78 }
79 else if (Dictionary2.ContainsKey(key2))
80 {
81 if (!Dictionary1.ContainsKey(key1))
82 throw new ArgumentException("key2 exists in the dictionary but not key1");
83 }
84
85 Dictionary1[key1] = value;
86 Dictionary2[key2] = value;
87 }
88 finally
89 {
90 if (gotLock)
91 rwLock.ExitWriteLock();
92 }
93 }
94
95 public bool Remove(TKey1 key1, TKey2 key2)
96 {
97 bool success;
98 bool gotLock = false;
99
100 try
101 {
102 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
103 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
104 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
105 try {}
106 finally
107 {
108 rwLock.EnterWriteLock();
109 gotLock = true;
110 }
111
112 Dictionary1.Remove(key1);
113 success = Dictionary2.Remove(key2);
114 }
115 finally
116 {
117 if (gotLock)
118 rwLock.ExitWriteLock();
119 }
120
121 return success;
122 }
123
124 public bool Remove(TKey1 key1)
125 {
126 bool found = false;
127 bool gotLock = false;
128
129 try
130 {
131 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
132 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
133 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
134 try {}
135 finally
136 {
137 rwLock.EnterWriteLock();
138 gotLock = true;
139 }
140
141 // This is an O(n) operation!
142 TValue value;
143 if (Dictionary1.TryGetValue(key1, out value))
144 {
145 foreach (KeyValuePair<TKey2, TValue> kvp in Dictionary2)
146 {
147 if (kvp.Value.Equals(value))
148 {
149 Dictionary1.Remove(key1);
150 Dictionary2.Remove(kvp.Key);
151 found = true;
152 break;
153 }
154 }
155 }
156 }
157 finally
158 {
159 if (gotLock)
160 rwLock.ExitWriteLock();
161 }
162
163 return found;
164 }
165
166 public bool Remove(TKey2 key2)
167 {
168 bool found = false;
169 bool gotLock = false;
170
171 try
172 {
173 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
174 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
175 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
176 try {}
177 finally
178 {
179 rwLock.EnterWriteLock();
180 gotLock = true;
181 }
182
183 // This is an O(n) operation!
184 TValue value;
185 if (Dictionary2.TryGetValue(key2, out value))
186 {
187 foreach (KeyValuePair<TKey1, TValue> kvp in Dictionary1)
188 {
189 if (kvp.Value.Equals(value))
190 {
191 Dictionary2.Remove(key2);
192 Dictionary1.Remove(kvp.Key);
193 found = true;
194 break;
195 }
196 }
197 }
198 }
199 finally
200 {
201 if (gotLock)
202 rwLock.ExitWriteLock();
203 }
204
205 return found;
206 }
207
208 public void Clear()
209 {
210 bool gotLock = false;
211
212 try
213 {
214 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
215 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
216 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
217 try {}
218 finally
219 {
220 rwLock.EnterWriteLock();
221 gotLock = true;
222 }
223
224 Dictionary1.Clear();
225 Dictionary2.Clear();
226 }
227 finally
228 {
229 if (gotLock)
230 rwLock.ExitWriteLock();
231 }
232 }
233
234 public int Count
235 {
236 get { return Dictionary1.Count; }
237 }
238
239 public bool ContainsKey(TKey1 key)
240 {
241 return Dictionary1.ContainsKey(key);
242 }
243
244 public bool ContainsKey(TKey2 key)
245 {
246 return Dictionary2.ContainsKey(key);
247 }
248
249 public bool TryGetValue(TKey1 key, out TValue value)
250 {
251 bool success;
252 bool gotLock = false;
253
254 try
255 {
256 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
257 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
258 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
259 try {}
260 finally
261 {
262 rwLock.EnterReadLock();
263 gotLock = true;
264 }
265
266 success = Dictionary1.TryGetValue(key, out value);
267 }
268 finally
269 {
270 if (gotLock)
271 rwLock.ExitReadLock();
272 }
273
274 return success;
275 }
276
277 public bool TryGetValue(TKey2 key, out TValue value)
278 {
279 bool success;
280 bool gotLock = false;
281
282 try
283 {
284 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
285 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
286 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
287 try {}
288 finally
289 {
290 rwLock.EnterReadLock();
291 gotLock = true;
292 }
293
294 success = Dictionary2.TryGetValue(key, out value);
295 }
296 finally
297 {
298 if (gotLock)
299 rwLock.ExitReadLock();
300 }
301
302 return success;
303 }
304
305 public void ForEach(Action<TValue> action)
306 {
307 bool gotLock = false;
308
309 try
310 {
311 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
312 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
313 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
314 try {}
315 finally
316 {
317 rwLock.EnterReadLock();
318 gotLock = true;
319 }
320
321 foreach (TValue value in Dictionary1.Values)
322 action(value);
323 }
324 finally
325 {
326 if (gotLock)
327 rwLock.ExitReadLock();
328 }
329 }
330
331 public void ForEach(Action<KeyValuePair<TKey1, TValue>> action)
332 {
333 bool gotLock = false;
334
335 try
336 {
337 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
338 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
339 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
340 try {}
341 finally
342 {
343 rwLock.EnterReadLock();
344 gotLock = true;
345 }
346
347 foreach (KeyValuePair<TKey1, TValue> entry in Dictionary1)
348 action(entry);
349 }
350 finally
351 {
352 if (gotLock)
353 rwLock.ExitReadLock();
354 }
355 }
356
357 public void ForEach(Action<KeyValuePair<TKey2, TValue>> action)
358 {
359 bool gotLock = false;
360
361 try
362 {
363 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
364 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
365 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
366 try {}
367 finally
368 {
369 rwLock.EnterReadLock();
370 gotLock = true;
371 }
372
373 foreach (KeyValuePair<TKey2, TValue> entry in Dictionary2)
374 action(entry);
375 }
376 finally
377 {
378 if (gotLock)
379 rwLock.ExitReadLock();
380 }
381 }
382
383 public TValue FindValue(Predicate<TValue> predicate)
384 {
385 bool gotLock = false;
386
387 try
388 {
389 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
390 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
391 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
392 try {}
393 finally
394 {
395 rwLock.EnterReadLock();
396 gotLock = true;
397 }
398
399 foreach (TValue value in Dictionary1.Values)
400 {
401 if (predicate(value))
402 return value;
403 }
404 }
405 finally
406 {
407 if (gotLock)
408 rwLock.ExitReadLock();
409 }
410
411 return default(TValue);
412 }
413
414 public IList<TValue> FindAll(Predicate<TValue> predicate)
415 {
416 IList<TValue> list = new List<TValue>();
417 bool gotLock = false;
418
419 try
420 {
421 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
422 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
423 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
424 try {}
425 finally
426 {
427 rwLock.EnterReadLock();
428 gotLock = true;
429 }
430
431 foreach (TValue value in Dictionary1.Values)
432 {
433 if (predicate(value))
434 list.Add(value);
435 }
436 }
437 finally
438 {
439 if (gotLock)
440 rwLock.ExitReadLock();
441 }
442
443 return list;
444 }
445
446 public int RemoveAll(Predicate<TValue> predicate)
447 {
448 IList<TKey1> list = new List<TKey1>();
449 bool gotUpgradeableLock = false;
450
451 try
452 {
453 // Avoid an asynchronous Thread.Abort() from possibly never existing an acquired lock by placing
454 // the acquision inside the main try. The inner finally block is needed because thread aborts cannot
455 // interrupt code in these blocks (hence gotLock is guaranteed to be set correctly).
456 try {}
457 finally
458 {
459 rwLock.EnterUpgradeableReadLock();
460 gotUpgradeableLock = true;
461 }
462
463 foreach (KeyValuePair<TKey1, TValue> kvp in Dictionary1)
464 {
465 if (predicate(kvp.Value))
466 list.Add(kvp.Key);
467 }
468
469 IList<TKey2> list2 = new List<TKey2>(list.Count);
470 foreach (KeyValuePair<TKey2, TValue> kvp in Dictionary2)
471 {
472 if (predicate(kvp.Value))
473 list2.Add(kvp.Key);
474 }
475
476 bool gotWriteLock = false;
477
478 try
479 {
480 try {}
481 finally
482 {
483 rwLock.EnterUpgradeableReadLock();
484 gotWriteLock = true;
485 }
486
487 for (int i = 0; i < list.Count; i++)
488 Dictionary1.Remove(list[i]);
489
490 for (int i = 0; i < list2.Count; i++)
491 Dictionary2.Remove(list2[i]);
492 }
493 finally
494 {
495 if (gotWriteLock)
496 rwLock.ExitWriteLock();
497 }
498 }
499 finally
500 {
501 if (gotUpgradeableLock)
502 rwLock.ExitUpgradeableReadLock();
503 }
504
505 return list.Count;
506 }
507 }
508} \ No newline at end of file
diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs
index fcc9873..948c259 100644
--- a/OpenSim/Framework/PrimitiveBaseShape.cs
+++ b/OpenSim/Framework/PrimitiveBaseShape.cs
@@ -192,18 +192,7 @@ namespace OpenSim.Framework
192 192
193 public PrimitiveBaseShape() 193 public PrimitiveBaseShape()
194 { 194 {
195 PCode = (byte) PCodeEnum.Primitive;
196 ExtraParams = new byte[1];
197 m_textureEntry = DEFAULT_TEXTURE;
198 }
199
200 public PrimitiveBaseShape(bool noShape)
201 {
202 if (noShape)
203 return;
204
205 PCode = (byte)PCodeEnum.Primitive; 195 PCode = (byte)PCodeEnum.Primitive;
206 ExtraParams = new byte[1];
207 m_textureEntry = DEFAULT_TEXTURE; 196 m_textureEntry = DEFAULT_TEXTURE;
208 } 197 }
209 198
@@ -216,7 +205,6 @@ namespace OpenSim.Framework
216// m_log.DebugFormat("[PRIMITIVE BASE SHAPE]: Creating from {0}", prim.ID); 205// m_log.DebugFormat("[PRIMITIVE BASE SHAPE]: Creating from {0}", prim.ID);
217 206
218 PCode = (byte)prim.PrimData.PCode; 207 PCode = (byte)prim.PrimData.PCode;
219 ExtraParams = new byte[1];
220 208
221 State = prim.PrimData.State; 209 State = prim.PrimData.State;
222 PathBegin = Primitive.PackBeginCut(prim.PrimData.PathBegin); 210 PathBegin = Primitive.PackBeginCut(prim.PrimData.PathBegin);
@@ -248,7 +236,10 @@ namespace OpenSim.Framework
248 SculptTexture = prim.Sculpt.SculptTexture; 236 SculptTexture = prim.Sculpt.SculptTexture;
249 SculptType = (byte)prim.Sculpt.Type; 237 SculptType = (byte)prim.Sculpt.Type;
250 } 238 }
251 else SculptType = (byte)OpenMetaverse.SculptType.None; 239 else
240 {
241 SculptType = (byte)OpenMetaverse.SculptType.None;
242 }
252 } 243 }
253 244
254 [XmlIgnore] 245 [XmlIgnore]
@@ -340,9 +331,9 @@ namespace OpenSim.Framework
340 _scale = new Vector3(side, side, side); 331 _scale = new Vector3(side, side, side);
341 } 332 }
342 333
343 public void SetHeigth(float heigth) 334 public void SetHeigth(float height)
344 { 335 {
345 _scale.Z = heigth; 336 _scale.Z = height;
346 } 337 }
347 338
348 public void SetRadius(float radius) 339 public void SetRadius(float radius)
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 93043cb..eefcdad 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -437,7 +437,7 @@ namespace OpenSim.Framework.Servers.HttpServer
437// reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]); 437// reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]);
438 //m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl); 438 //m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl);
439 439
440 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); 440 Culture.SetCurrentCulture();
441 441
442// // This is the REST agent interface. We require an agent to properly identify 442// // This is the REST agent interface. We require an agent to properly identify
443// // itself. If the REST handler recognizes the prefix it will attempt to 443// // itself. If the REST handler recognizes the prefix it will attempt to
diff --git a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
index a933ae0..0fbdaf3 100644
--- a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
+++ b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
@@ -303,10 +303,6 @@ namespace OpenSim.Framework.Tests
303 Culture.SetCurrentCulture(); 303 Culture.SetCurrentCulture();
304 Assert.That(Thread.CurrentThread.CurrentCulture.Name == ci.Name, "SetCurrentCulture failed to set thread culture to en-US"); 304 Assert.That(Thread.CurrentThread.CurrentCulture.Name == ci.Name, "SetCurrentCulture failed to set thread culture to en-US");
305 305
306 } 306 }
307
308
309
310 } 307 }
311} 308} \ No newline at end of file
312
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
index 0872cc8..fd02b08 100644
--- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
+++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
@@ -53,8 +53,10 @@ namespace OpenSim.Region.CoreModules.Asset.Tests
53 protected FlotsamAssetCache m_cache; 53 protected FlotsamAssetCache m_cache;
54 54
55 [SetUp] 55 [SetUp]
56 public void SetUp() 56 public override void SetUp()
57 { 57 {
58 base.SetUp();
59
58 IConfigSource config = new IniConfigSource(); 60 IConfigSource config = new IniConfigSource();
59 61
60 config.AddConfig("Modules"); 62 config.AddConfig("Modules");
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index cc266df..1627f6c 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -153,7 +153,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
153 if (sp != null && !sp.IsChildAgent) 153 if (sp != null && !sp.IsChildAgent)
154 { 154 {
155 // Local message 155 // Local message
156 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); 156// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
157 157
158 sp.ControllingClient.SendInstantMessage(im); 158 sp.ControllingClient.SendInstantMessage(im);
159 159
@@ -166,14 +166,14 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
166 // try child avatar second 166 // try child avatar second
167 foreach (Scene scene in m_Scenes) 167 foreach (Scene scene in m_Scenes)
168 { 168 {
169 //m_log.DebugFormat( 169// m_log.DebugFormat(
170 // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); 170// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
171 171
172 ScenePresence sp = scene.GetScenePresence(toAgentID); 172 ScenePresence sp = scene.GetScenePresence(toAgentID);
173 if (sp != null) 173 if (sp != null)
174 { 174 {
175 // Local message 175 // Local message
176 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID); 176// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID);
177 177
178 sp.ControllingClient.SendInstantMessage(im); 178 sp.ControllingClient.SendInstantMessage(im);
179 179
@@ -183,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
183 } 183 }
184 } 184 }
185 185
186 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); 186// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
187 187
188 SendGridInstantMessageViaXMLRPC(im, result); 188 SendGridInstantMessageViaXMLRPC(im, result);
189 } 189 }
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
index b768257..ac25a93 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
@@ -57,8 +57,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
57 protected TestClient m_tc; 57 protected TestClient m_tc;
58 58
59 [SetUp] 59 [SetUp]
60 public void SetUp() 60 public override void SetUp()
61 { 61 {
62 base.SetUp();
63
62 m_iam = new BasicInventoryAccessModule(); 64 m_iam = new BasicInventoryAccessModule();
63 65
64 IConfigSource config = new IniConfigSource(); 66 IConfigSource config = new IniConfigSource();
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
index 7e365ca..69bac82 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
@@ -46,8 +46,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests
46 public class PresenceConnectorsTests : OpenSimTestCase 46 public class PresenceConnectorsTests : OpenSimTestCase
47 { 47 {
48 LocalPresenceServicesConnector m_LocalConnector; 48 LocalPresenceServicesConnector m_LocalConnector;
49 private void SetUp() 49
50 public override void SetUp()
50 { 51 {
52 base.SetUp();
53
51 IConfigSource config = new IniConfigSource(); 54 IConfigSource config = new IniConfigSource();
52 config.AddConfig("Modules"); 55 config.AddConfig("Modules");
53 config.AddConfig("PresenceService"); 56 config.AddConfig("PresenceService");
diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
index 14eca42..0945b43 100644
--- a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
+++ b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
@@ -60,8 +60,10 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
60 protected ILandObject m_lo2; 60 protected ILandObject m_lo2;
61 61
62 [SetUp] 62 [SetUp]
63 public void SetUp() 63 public override void SetUp()
64 { 64 {
65 base.SetUp();
66
65 m_pcm = new PrimCountModule(); 67 m_pcm = new PrimCountModule();
66 LandManagementModule lmm = new LandManagementModule(); 68 LandManagementModule lmm = new LandManagementModule();
67 m_scene = new SceneHelpers().SetupScene(); 69 m_scene = new SceneHelpers().SetupScene();
diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
index ba4b041..03a96a4 100644
--- a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
+++ b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
@@ -50,8 +50,10 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
50 protected MoapModule m_module; 50 protected MoapModule m_module;
51 51
52 [SetUp] 52 [SetUp]
53 public void SetUp() 53 public override void SetUp()
54 { 54 {
55 base.SetUp();
56
55 m_module = new MoapModule(); 57 m_module = new MoapModule();
56 m_scene = new SceneHelpers().SetupScene(); 58 m_scene = new SceneHelpers().SetupScene();
57 SceneHelpers.SetupSceneModules(m_scene, m_module); 59 SceneHelpers.SetupSceneModules(m_scene, m_module);
diff --git a/OpenSim/Region/Framework/Scenes/EntityManager.cs b/OpenSim/Region/Framework/Scenes/EntityManager.cs
index b788a3c..7181313 100644
--- a/OpenSim/Region/Framework/Scenes/EntityManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EntityManager.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using log4net; 32using log4net;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenSim.Framework;
34 35
35namespace OpenSim.Region.Framework.Scenes 36namespace OpenSim.Region.Framework.Scenes
36{ 37{
@@ -38,7 +39,8 @@ namespace OpenSim.Region.Framework.Scenes
38 { 39 {
39// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 41
41 private readonly DoubleDictionary<UUID, uint, EntityBase> m_entities = new DoubleDictionary<UUID, uint, EntityBase>(); 42 private readonly DoubleDictionaryThreadAbortSafe<UUID, uint, EntityBase> m_entities
43 = new DoubleDictionaryThreadAbortSafe<UUID, uint, EntityBase>();
42 44
43 public int Count 45 public int Count
44 { 46 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 6a0f472..2a1949d 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -6041,10 +6041,17 @@ Environment.Exit(1);
6041 GC.Collect(); 6041 GC.Collect();
6042 } 6042 }
6043 6043
6044 // Wrappers to get physics modules retrieve assets. Has to be done this way 6044 /// <summary>
6045 // because we can't assign the asset service to physics directly - at the 6045 /// Wrappers to get physics modules retrieve assets.
6046 // time physics are instantiated it's not registered but it will be by 6046 /// </summary>
6047 // the time the first prim exists. 6047 /// <remarks>
6048 /// Has to be done this way
6049 /// because we can't assign the asset service to physics directly - at the
6050 /// time physics are instantiated it's not registered but it will be by
6051 /// the time the first prim exists.
6052 /// </remarks>
6053 /// <param name="assetID"></param>
6054 /// <param name="callback"></param>
6048 public void PhysicsRequestAsset(UUID assetID, AssetReceivedDelegate callback) 6055 public void PhysicsRequestAsset(UUID assetID, AssetReceivedDelegate callback)
6049 { 6056 {
6050 AssetService.Get(assetID.ToString(), callback, PhysicsAssetReceived); 6057 AssetService.Get(assetID.ToString(), callback, PhysicsAssetReceived);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index be8a502..fa3110c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -24,21 +24,10 @@
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 * The quotations from http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial
28/* RA: June 14, 2011. Copied from ODEDynamics.cs and converted to 28 * are Copyright (c) 2009 Linden Research, Inc and are used under their license
29 * call the BulletSim system. 29 * of Creative Commons Attribution-Share Alike 3.0
30 */ 30 * (http://creativecommons.org/licenses/by-sa/3.0/).
31/* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces
32 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
33 * ODEPrim.cs contains methods dealing with Prim editing, Prim
34 * characteristics and Kinetic motion.
35 * ODEDynamics.cs contains methods dealing with Prim Physical motion
36 * (dynamics) and the associated settings. Old Linear and angular
37 * motors for dynamic motion have been replace with MoveLinear()
38 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
39 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
40 * switch between 'VEHICLE' parameter use and general dynamics
41 * settings use.
42 */ 31 */
43 32
44using System; 33using System;
@@ -111,7 +100,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
111 private float m_bankingEfficiency = 0; 100 private float m_bankingEfficiency = 0;
112 private float m_bankingMix = 0; 101 private float m_bankingMix = 0;
113 private float m_bankingTimescale = 0; 102 private float m_bankingTimescale = 0;
114 private Vector3 m_lastBanking = Vector3.Zero;
115 103
116 //Hover and Buoyancy properties 104 //Hover and Buoyancy properties
117 private float m_VhoverHeight = 0f; 105 private float m_VhoverHeight = 0f;
@@ -125,8 +113,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
125 113
126 //Attractor properties 114 //Attractor properties
127 private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction"); 115 private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction");
128 private float m_verticalAttractionEfficiency = 1.0f; // damped 116 private float m_verticalAttractionEfficiency = 1.0f; // damped
129 private float m_verticalAttractionTimescale = 600f; // Timescale > 500 means no vert attractor. 117 private float m_verticalAttractionCutoff = 500f; // per the documentation
118 // Timescale > cutoff means no vert attractor.
119 private float m_verticalAttractionTimescale = 510f;
130 120
131 public BSDynamics(BSScene myScene, BSPrim myPrim) 121 public BSDynamics(BSScene myScene, BSPrim myPrim)
132 { 122 {
@@ -329,7 +319,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
329 m_bankingEfficiency = 0; 319 m_bankingEfficiency = 0;
330 m_bankingTimescale = 1000; 320 m_bankingTimescale = 1000;
331 m_bankingMix = 1; 321 m_bankingMix = 1;
332 m_lastBanking = Vector3.Zero;
333 322
334 m_referenceFrame = Quaternion.Identity; 323 m_referenceFrame = Quaternion.Identity;
335 m_flags = (VehicleFlag)0; 324 m_flags = (VehicleFlag)0;
@@ -364,7 +353,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
364 m_bankingEfficiency = 0; 353 m_bankingEfficiency = 0;
365 m_bankingTimescale = 10; 354 m_bankingTimescale = 10;
366 m_bankingMix = 1; 355 m_bankingMix = 1;
367 m_lastBanking = Vector3.Zero;
368 356
369 m_referenceFrame = Quaternion.Identity; 357 m_referenceFrame = Quaternion.Identity;
370 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY 358 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
@@ -374,6 +362,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
374 m_flags |= (VehicleFlag.NO_DEFLECTION_UP 362 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
375 | VehicleFlag.LIMIT_ROLL_ONLY 363 | VehicleFlag.LIMIT_ROLL_ONLY
376 | VehicleFlag.LIMIT_MOTOR_UP); 364 | VehicleFlag.LIMIT_MOTOR_UP);
365
377 break; 366 break;
378 case Vehicle.TYPE_CAR: 367 case Vehicle.TYPE_CAR:
379 m_linearMotorDirection = Vector3.Zero; 368 m_linearMotorDirection = Vector3.Zero;
@@ -403,7 +392,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
403 m_bankingEfficiency = -0.2f; 392 m_bankingEfficiency = -0.2f;
404 m_bankingMix = 1; 393 m_bankingMix = 1;
405 m_bankingTimescale = 1; 394 m_bankingTimescale = 1;
406 m_lastBanking = Vector3.Zero;
407 395
408 m_referenceFrame = Quaternion.Identity; 396 m_referenceFrame = Quaternion.Identity;
409 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY 397 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
@@ -442,7 +430,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
442 m_bankingEfficiency = -0.3f; 430 m_bankingEfficiency = -0.3f;
443 m_bankingMix = 0.8f; 431 m_bankingMix = 0.8f;
444 m_bankingTimescale = 1; 432 m_bankingTimescale = 1;
445 m_lastBanking = Vector3.Zero;
446 433
447 m_referenceFrame = Quaternion.Identity; 434 m_referenceFrame = Quaternion.Identity;
448 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY 435 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY
@@ -481,7 +468,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
481 m_bankingEfficiency = 1; 468 m_bankingEfficiency = 1;
482 m_bankingMix = 0.7f; 469 m_bankingMix = 0.7f;
483 m_bankingTimescale = 2; 470 m_bankingTimescale = 2;
484 m_lastBanking = Vector3.Zero;
485 471
486 m_referenceFrame = Quaternion.Identity; 472 m_referenceFrame = Quaternion.Identity;
487 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY 473 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
@@ -520,7 +506,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
520 m_bankingEfficiency = 0; 506 m_bankingEfficiency = 0;
521 m_bankingMix = 0.7f; 507 m_bankingMix = 0.7f;
522 m_bankingTimescale = 5; 508 m_bankingTimescale = 5;
523 m_lastBanking = Vector3.Zero;
524 509
525 m_referenceFrame = Quaternion.Identity; 510 m_referenceFrame = Quaternion.Identity;
526 511
@@ -554,8 +539,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
554 // Z goes away and we keep X and Y 539 // Z goes away and we keep X and Y
555 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f); 540 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
556 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) 541 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
557
558 // m_bankingMotor = new BSVMotor("BankingMotor", ...);
559 } 542 }
560 543
561 // Some of the properties of this prim may have changed. 544 // Some of the properties of this prim may have changed.
@@ -577,15 +560,23 @@ namespace OpenSim.Region.Physics.BulletSPlugin
577 float angularDamping = PhysicsScene.Params.vehicleAngularDamping; 560 float angularDamping = PhysicsScene.Params.vehicleAngularDamping;
578 BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping); 561 BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping);
579 562
563 // Vehicles report collision events so we know when it's on the ground
564 BulletSimAPI.AddToCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS);
565
580 // DEBUG DEBUG DEBUG: use uniform inertia to smooth movement added by Bullet 566 // DEBUG DEBUG DEBUG: use uniform inertia to smooth movement added by Bullet
581 // Vector3 localInertia = new Vector3(1f, 1f, 1f); 567 // Vector3 localInertia = new Vector3(1f, 1f, 1f);
582 Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass); 568 // Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass);
569 Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(Prim.PhysShape.ptr, m_vehicleMass);
583 BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia); 570 BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
584 BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr); 571 BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr);
585 572
586 VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}", 573 VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}",
587 Prim.LocalID, friction, localInertia, angularDamping); 574 Prim.LocalID, friction, localInertia, angularDamping);
588 } 575 }
576 else
577 {
578 BulletSimAPI.RemoveFromCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS);
579 }
589 } 580 }
590 581
591 public bool RemoveBodyDependencies(BSPhysObject prim) 582 public bool RemoveBodyDependencies(BSPhysObject prim)
@@ -618,13 +609,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
618 private float? m_knownWaterLevel; 609 private float? m_knownWaterLevel;
619 private Vector3? m_knownPosition; 610 private Vector3? m_knownPosition;
620 private Vector3? m_knownVelocity; 611 private Vector3? m_knownVelocity;
612 private Vector3 m_knownForce;
621 private Quaternion? m_knownOrientation; 613 private Quaternion? m_knownOrientation;
622 private Vector3? m_knownRotationalVelocity; 614 private Vector3? m_knownRotationalVelocity;
615 private Vector3 m_knownRotationalForce;
616 private float? m_knownForwardSpeed;
623 617
624 private const int m_knownChangedPosition = 1 << 0; 618 private const int m_knownChangedPosition = 1 << 0;
625 private const int m_knownChangedVelocity = 1 << 1; 619 private const int m_knownChangedVelocity = 1 << 1;
626 private const int m_knownChangedOrientation = 1 << 2; 620 private const int m_knownChangedForce = 1 << 2;
627 private const int m_knownChangedRotationalVelocity = 1 << 3; 621 private const int m_knownChangedOrientation = 1 << 3;
622 private const int m_knownChangedRotationalVelocity = 1 << 4;
623 private const int m_knownChangedRotationalForce = 1 << 5;
628 624
629 private void ForgetKnownVehicleProperties() 625 private void ForgetKnownVehicleProperties()
630 { 626 {
@@ -632,8 +628,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
632 m_knownWaterLevel = null; 628 m_knownWaterLevel = null;
633 m_knownPosition = null; 629 m_knownPosition = null;
634 m_knownVelocity = null; 630 m_knownVelocity = null;
631 m_knownForce = Vector3.Zero;
635 m_knownOrientation = null; 632 m_knownOrientation = null;
636 m_knownRotationalVelocity = null; 633 m_knownRotationalVelocity = null;
634 m_knownRotationalForce = Vector3.Zero;
635 m_knownForwardSpeed = null;
637 m_knownChanged = 0; 636 m_knownChanged = 0;
638 } 637 }
639 private void PushKnownChanged() 638 private void PushKnownChanged()
@@ -645,12 +644,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin
645 if ((m_knownChanged & m_knownChangedOrientation) != 0) 644 if ((m_knownChanged & m_knownChangedOrientation) != 0)
646 Prim.ForceOrientation = VehicleOrientation; 645 Prim.ForceOrientation = VehicleOrientation;
647 if ((m_knownChanged & m_knownChangedVelocity) != 0) 646 if ((m_knownChanged & m_knownChangedVelocity) != 0)
647 {
648 Prim.ForceVelocity = VehicleVelocity; 648 Prim.ForceVelocity = VehicleVelocity;
649 BulletSimAPI.SetInterpolationLinearVelocity2(Prim.PhysBody.ptr, VehicleVelocity);
650 }
651 if ((m_knownChanged & m_knownChangedForce) != 0)
652 Prim.AddForce((Vector3)m_knownForce, false, true);
653
649 if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) 654 if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0)
650 { 655 {
651 Prim.ForceRotationalVelocity = VehicleRotationalVelocity; 656 Prim.ForceRotationalVelocity = VehicleRotationalVelocity;
657 // Fake out Bullet by making it think the velocity is the same as last time.
652 BulletSimAPI.SetInterpolationAngularVelocity2(Prim.PhysBody.ptr, VehicleRotationalVelocity); 658 BulletSimAPI.SetInterpolationAngularVelocity2(Prim.PhysBody.ptr, VehicleRotationalVelocity);
653 } 659 }
660 if ((m_knownChanged & m_knownChangedRotationalForce) != 0)
661 Prim.AddAngularForce((Vector3)m_knownRotationalForce, false, true);
662
654 // If we set one of the values (ie, the physics engine didn't do it) we must force 663 // If we set one of the values (ie, the physics engine didn't do it) we must force
655 // an UpdateProperties event to send the changes up to the simulator. 664 // an UpdateProperties event to send the changes up to the simulator.
656 BulletSimAPI.PushUpdate2(Prim.PhysBody.ptr); 665 BulletSimAPI.PushUpdate2(Prim.PhysBody.ptr);
@@ -720,6 +729,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
720 } 729 }
721 } 730 }
722 731
732 private void VehicleAddForce(Vector3 aForce)
733 {
734 m_knownForce += aForce;
735 m_knownChanged |= m_knownChangedForce;
736 }
737
723 private Vector3 VehicleRotationalVelocity 738 private Vector3 VehicleRotationalVelocity
724 { 739 {
725 get 740 get
@@ -734,6 +749,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin
734 m_knownChanged |= m_knownChangedRotationalVelocity; 749 m_knownChanged |= m_knownChangedRotationalVelocity;
735 } 750 }
736 } 751 }
752 private void VehicleAddAngularForce(Vector3 aForce)
753 {
754 m_knownRotationalForce += aForce;
755 m_knownChanged |= m_knownChangedRotationalForce;
756 }
757 private float VehicleForwardSpeed
758 {
759 get
760 {
761 if (m_knownForwardSpeed == null)
762 m_knownForwardSpeed = (VehicleVelocity * Quaternion.Inverse(VehicleOrientation)).X;
763 return (float)m_knownForwardSpeed;
764 }
765 }
766
737 #endregion // Known vehicle value functions 767 #endregion // Known vehicle value functions
738 768
739 // One step of the vehicle properties for the next 'pTimestep' seconds. 769 // One step of the vehicle properties for the next 'pTimestep' seconds.
@@ -769,10 +799,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
769 linearMotorContribution *= VehicleOrientation; 799 linearMotorContribution *= VehicleOrientation;
770 800
771 // ================================================================== 801 // ==================================================================
772 // Gravity and Buoyancy 802 // Buoyancy: force to overcome gravity.
773 // There is some gravity, make a gravity force vector that is applied after object velocity.
774 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 803 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
775 Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); 804 // So, if zero, don't change anything (let gravity happen). If one, negate the effect of gravity.
805 Vector3 buoyancyContribution = Prim.PhysicsScene.DefaultGravity * m_VehicleBuoyancy;
776 806
777 Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep); 807 Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep);
778 808
@@ -797,14 +827,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
797 newVelocity.Z = 0; 827 newVelocity.Z = 0;
798 828
799 // ================================================================== 829 // ==================================================================
800 // Clamp REALLY high or low velocities 830 // Clamp high or low velocities
801 float newVelocityLengthSq = newVelocity.LengthSquared(); 831 float newVelocityLengthSq = newVelocity.LengthSquared();
802 if (newVelocityLengthSq > 1e6f) 832 // if (newVelocityLengthSq > 1e6f)
833 if (newVelocityLengthSq > 1000f)
803 { 834 {
804 newVelocity /= newVelocity.Length(); 835 newVelocity /= newVelocity.Length();
805 newVelocity *= 1000f; 836 newVelocity *= 1000f;
806 } 837 }
807 else if (newVelocityLengthSq < 1e-6f) 838 // else if (newVelocityLengthSq < 1e-6f)
839 else if (newVelocityLengthSq < 0.001f)
808 newVelocity = Vector3.Zero; 840 newVelocity = Vector3.Zero;
809 841
810 // ================================================================== 842 // ==================================================================
@@ -813,15 +845,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
813 VehicleVelocity = newVelocity; 845 VehicleVelocity = newVelocity;
814 846
815 // Other linear forces are applied as forces. 847 // Other linear forces are applied as forces.
816 Vector3 totalDownForce = grav * m_vehicleMass * pTimestep; 848 Vector3 totalDownForce = buoyancyContribution * m_vehicleMass;
817 if (totalDownForce != Vector3.Zero) 849 if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f))
818 { 850 {
819 Prim.AddForce(totalDownForce, false); 851 VehicleAddForce(totalDownForce);
820 } 852 }
821 853
822 VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},linContrib={3},terrContrib={4},hoverContrib={5},limitContrib={6}", 854 VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},IsColliding={3}",
823 Prim.LocalID, newVelocity, totalDownForce, 855 Prim.LocalID, newVelocity, totalDownForce, Prim.IsColliding);
824 linearMotorContribution, terrainHeightContribution, hoverContribution, limitMotorUpContribution 856 VDetailLog("{0}, MoveLinear,done,linContrib={1},terrContrib={2},hoverContrib={3},limitContrib={4},buoyContrib={5}",
857 Prim.LocalID,
858 linearMotorContribution, terrainHeightContribution, hoverContribution,
859 limitMotorUpContribution, buoyancyContribution
825 ); 860 );
826 861
827 } // end MoveLinear() 862 } // end MoveLinear()
@@ -942,21 +977,24 @@ namespace OpenSim.Region.Physics.BulletSPlugin
942 } 977 }
943 978
944 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : 979 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
945 // Prevent ground vehicles from motoring into the sky.This flag has a subtle effect when 980 // Prevent ground vehicles from motoring into the sky. This flag has a subtle effect when
946 // used with conjunction with banking: the strength of the banking will decay when the 981 // used with conjunction with banking: the strength of the banking will decay when the
947 // vehicle no longer experiences collisions. The decay timescale is the same as 982 // vehicle no longer experiences collisions. The decay timescale is the same as
948 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering 983 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering
949 // when they are in mid jump. 984 // when they are in mid jump.
950 // TODO: this code is wrong. Also, what should it do for boats? 985 // TODO: this code is wrong. Also, what should it do for boats (height from water)?
986 // This is just using the ground and a general collision check. Should really be using
987 // a downward raycast to find what is below.
951 public Vector3 ComputeLinearMotorUp(float pTimestep) 988 public Vector3 ComputeLinearMotorUp(float pTimestep)
952 { 989 {
953 Vector3 ret = Vector3.Zero; 990 Vector3 ret = Vector3.Zero;
991
954 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) 992 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
955 { 993 {
956 // If the vehicle is motoring into the sky, get it going back down. 994 // If the vehicle is motoring into the sky, get it going back down.
957 // float distanceAboveGround = pos.Z - Math.Max(GetTerrainHeight(pos), GetWaterLevel(pos));
958 float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition); 995 float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition);
959 if (distanceAboveGround > 1f) 996 // Not colliding if the vehicle is off the ground
997 if (!Prim.IsColliding)
960 { 998 {
961 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep); 999 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep);
962 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); 1000 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
@@ -977,8 +1015,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
977 // ======================================================================= 1015 // =======================================================================
978 // Apply the effect of the angular motor. 1016 // Apply the effect of the angular motor.
979 // The 'contribution' is how much angular correction velocity each function wants. 1017 // The 'contribution' is how much angular correction velocity each function wants.
980 // All the contributions are added together and the orientation of the vehicle 1018 // All the contributions are added together and the resulting velocity is
981 // is changed by all the contributed corrections. 1019 // set directly on the vehicle.
982 private void MoveAngular(float pTimestep) 1020 private void MoveAngular(float pTimestep)
983 { 1021 {
984 // The user wants how many radians per second angular change? 1022 // The user wants how many radians per second angular change?
@@ -1001,7 +1039,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1001 1039
1002 Vector3 deflectionContribution = ComputeAngularDeflection(); 1040 Vector3 deflectionContribution = ComputeAngularDeflection();
1003 1041
1004 Vector3 bankingContribution = ComputeAngularBanking(angularMotorContribution.Z); 1042 Vector3 bankingContribution = ComputeAngularBanking();
1005 1043
1006 // ================================================================== 1044 // ==================================================================
1007 m_lastVertAttractor = verticalAttractionContribution; 1045 m_lastVertAttractor = verticalAttractionContribution;
@@ -1013,11 +1051,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1013 + bankingContribution; 1051 + bankingContribution;
1014 1052
1015 // ================================================================== 1053 // ==================================================================
1016 // The correction is applied to the current orientation. 1054 // Apply the correction velocity.
1055 // TODO: Should this be applied as an angular force (torque)?
1017 if (!m_lastAngularCorrection.ApproxEquals(Vector3.Zero, 0.01f)) 1056 if (!m_lastAngularCorrection.ApproxEquals(Vector3.Zero, 0.01f))
1018 { 1057 {
1019 Vector3 scaledCorrection = m_lastAngularCorrection * pTimestep; 1058 Vector3 scaledCorrection = m_lastAngularCorrection * pTimestep;
1020
1021 VehicleRotationalVelocity = scaledCorrection; 1059 VehicleRotationalVelocity = scaledCorrection;
1022 1060
1023 VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5},scaledCorr={6}", 1061 VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5},scaledCorr={6}",
@@ -1029,7 +1067,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1029 } 1067 }
1030 else 1068 else
1031 { 1069 {
1032 // The vehicle is not adding anything velocity wise. 1070 // The vehicle is not adding anything angular wise.
1033 VehicleRotationalVelocity = Vector3.Zero; 1071 VehicleRotationalVelocity = Vector3.Zero;
1034 VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID); 1072 VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID);
1035 } 1073 }
@@ -1060,19 +1098,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1060 torqueFromOffset.Y = 0; 1098 torqueFromOffset.Y = 0;
1061 if (float.IsNaN(torqueFromOffset.Z)) 1099 if (float.IsNaN(torqueFromOffset.Z))
1062 torqueFromOffset.Z = 0; 1100 torqueFromOffset.Z = 0;
1063 torqueFromOffset *= m_vehicleMass; 1101
1064 Prim.ApplyTorqueImpulse(torqueFromOffset, true); 1102 VehicleAddAngularForce(torqueFromOffset * m_vehicleMass);
1065 VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); 1103 VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset);
1066 } 1104 }
1067 1105
1068 } 1106 }
1069 1107 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
1108 // Some vehicles, like boats, should always keep their up-side up. This can be done by
1109 // enabling the "vertical attractor" behavior that springs the vehicle's local z-axis to
1110 // the world z-axis (a.k.a. "up"). To take advantage of this feature you would set the
1111 // VEHICLE_VERTICAL_ATTRACTION_TIMESCALE to control the period of the spring frequency,
1112 // and then set the VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY to control the damping. An
1113 // efficiency of 0.0 will cause the spring to wobble around its equilibrium, while an
1114 // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay.
1070 public Vector3 ComputeAngularVerticalAttraction() 1115 public Vector3 ComputeAngularVerticalAttraction()
1071 { 1116 {
1072 Vector3 ret = Vector3.Zero; 1117 Vector3 ret = Vector3.Zero;
1073 1118
1074 // If vertical attaction timescale is reasonable and we applied an angular force last time... 1119 // If vertical attaction timescale is reasonable and we applied an angular force last time...
1075 if (m_verticalAttractionTimescale < 500) 1120 if (m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1076 { 1121 {
1077 // Take a vector pointing up and convert it from world to vehicle relative coords. 1122 // Take a vector pointing up and convert it from world to vehicle relative coords.
1078 Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; 1123 Vector3 verticalError = Vector3.UnitZ * VehicleOrientation;
@@ -1097,91 +1142,121 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1097 ret.Y = - verticalError.X; 1142 ret.Y = - verticalError.X;
1098 ret.Z = 0f; 1143 ret.Z = 0f;
1099 1144
1100 // scale by the time scale and timestep 1145 // Scale the correction force by how far we're off from vertical.
1146 // Z error of one says little error. As Z gets smaller, the vehicle is leaning farther over.
1147 float clampedSqrZError = ClampInRange(0.01f, verticalError.Z * verticalError.Z, 1f);
1148 float vertForce = 1f / clampedSqrZError;
1149
1150 ret *= vertForce;
1151
1152 // Correction happens over a number of seconds.
1101 Vector3 unscaledContrib = ret; 1153 Vector3 unscaledContrib = ret;
1102 ret /= m_verticalAttractionTimescale; 1154 ret /= m_verticalAttractionTimescale;
1103 // This returns the angular correction desired. Timestep is added later. 1155
1104 // ret *= pTimestep; 1156 VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},vertForce={3},eff={4},vertAttr={5}",
1105 1157 Prim.LocalID, verticalError, unscaledContrib, vertForce, m_verticalAttractionEfficiency, ret);
1106 // apply efficiency
1107 Vector3 preEfficiencyContrib = ret;
1108 // TODO: implement efficiency.
1109 // Effenciency squared seems to give a more realistic effect
1110 float efficencySquared = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency;
1111 // ret *= efficencySquared;
1112
1113 VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},preEff={3},eff={4},effSq={5},vertAttr={6}",
1114 Prim.LocalID, verticalError, unscaledContrib, preEfficiencyContrib,
1115 m_verticalAttractionEfficiency, efficencySquared,
1116 ret);
1117 } 1158 }
1118 return ret; 1159 return ret;
1119 } 1160 }
1120 1161
1121 // Return the angular correction to correct the direction the vehicle is pointing to be 1162 // Return the angular correction to correct the direction the vehicle is pointing to be
1122 // the direction is should want to be pointing. 1163 // the direction is should want to be pointing.
1164 // The vehicle is moving in some direction and correct its orientation to it is pointing
1165 // in that direction.
1166 // TODO: implement reference frame.
1123 public Vector3 ComputeAngularDeflection() 1167 public Vector3 ComputeAngularDeflection()
1124 { 1168 {
1125 Vector3 ret = Vector3.Zero; 1169 Vector3 ret = Vector3.Zero;
1170 return ret; // DEBUG DEBUG DEBUG debug one force at a time
1126 1171
1127 if (m_angularDeflectionEfficiency != 0) 1172 if (m_angularDeflectionEfficiency != 0)
1128 { 1173 {
1129 // Where the vehicle should want to point relative to the vehicle 1174 // The direction the vehicle is moving
1130 Vector3 preferredDirection = Vector3.UnitX * m_referenceFrame; 1175 Vector3 movingDirection = VehicleVelocity;
1176 movingDirection.Normalize();
1131 1177
1132 // Where the vehicle is pointing relative to the vehicle. 1178 // The direction the vehicle is pointing
1133 Vector3 currentDirection = Vector3.UnitX * Quaternion.Add(VehicleOrientation, m_referenceFrame); 1179 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
1180 pointingDirection.Normalize();
1134 1181
1135 // Difference between where vehicle is pointing and where it should wish to point 1182 // The difference between what is and what should be
1136 Vector3 directionCorrection = preferredDirection - currentDirection; 1183 Vector3 deflectionError = movingDirection - pointingDirection;
1137 1184
1138 // Scale the correction by recovery timescale and efficiency 1185 // Scale the correction by recovery timescale and efficiency
1139 ret = directionCorrection * m_angularDeflectionEfficiency / m_angularDeflectionTimescale; 1186 ret = (-deflectionError * VehicleForwardSpeed) * m_angularDeflectionEfficiency;
1187 ret /= m_angularDeflectionTimescale;
1140 1188
1141 VDetailLog("{0}, MoveAngular,Deflection,perfDir={1},currentDir={2},dirCorrection={3},ret={4}", 1189 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}",
1142 Prim.LocalID, preferredDirection, currentDirection, directionCorrection, ret); 1190 Prim.LocalID, movingDirection, pointingDirection, deflectionError, ret);
1143 } 1191 }
1144 return ret; 1192 return ret;
1145 } 1193 }
1146 1194
1147 // Return an angular change to tip the vehicle (around X axis) when turning (turned around Z). 1195 // Return an angular change to rotate the vehicle around the Z axis when the vehicle
1148 // Remembers the last banking value calculated and returns the difference needed this tick. 1196 // is tipped around the X axis.
1149 // TurningFactor is rate going left or right (pos=left, neg=right, scale=0..1). 1197 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
1150 public Vector3 ComputeAngularBanking(float turningFactor) 1198 // The vertical attractor feature must be enabled in order for the banking behavior to
1199 // function. The way banking works is this: a rotation around the vehicle's roll-axis will
1200 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude
1201 // of the yaw effect will be proportional to the
1202 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's
1203 // velocity along its preferred axis of motion.
1204 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any
1205 // positive rotation (by the right-hand rule) about the roll-axis will effect a
1206 // (negative) torque around the yaw-axis, making it turn to the right--that is the
1207 // vehicle will lean into the turn, which is how real airplanes and motorcycle's work.
1208 // Negating the banking coefficient will make it so that the vehicle leans to the
1209 // outside of the turn (not very "physical" but might allow interesting vehicles so why not?).
1210 // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making
1211 // banking vehicles do what you want rather than what the laws of physics allow.
1212 // For example, consider a real motorcycle...it must be moving forward in order for
1213 // it to turn while banking, however video-game motorcycles are often configured
1214 // to turn in place when at a dead stop--because they are often easier to control
1215 // that way using the limited interface of the keyboard or game controller. The
1216 // VEHICLE_BANKING_MIX enables combinations of both realistic and non-realistic
1217 // banking by functioning as a slider between a banking that is correspondingly
1218 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the
1219 // banking effect depends only on the vehicle's rotation about its roll-axis compared
1220 // to "dynamic" where the banking is also proportional to its velocity along its
1221 // roll-axis. Finding the best value of the "mixture" will probably require trial and error.
1222 // The time it takes for the banking behavior to defeat a preexisting angular velocity about the
1223 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to
1224 // bank quickly then give it a banking timescale of about a second or less, otherwise you can
1225 // make a sluggish vehicle by giving it a timescale of several seconds.
1226 public Vector3 ComputeAngularBanking()
1151 { 1227 {
1152 Vector3 ret = Vector3.Zero; 1228 Vector3 ret = Vector3.Zero;
1153 Vector3 computedBanking = Vector3.Zero;
1154 1229
1155 if (m_bankingEfficiency != 0) 1230 if (m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1156 { 1231 {
1157 Vector3 currentDirection = Vector3.UnitX * VehicleOrientation; 1232 // This works by rotating a unit vector to the orientation of the vehicle. The
1158 1233 // roll (tilt) will be Y component of a tilting Z vector (zero for no tilt
1159 float mult = (m_bankingMix * m_bankingMix) * -1 * (m_bankingMix < 0 ? -1 : 1); 1234 // up to one for full over).
1235 Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation;
1160 1236
1161 //Use the square of the efficiency, as it looks much more how SL banking works 1237 // Figure out the yaw value for this much roll.
1162 float effSquared = (m_bankingEfficiency * m_bankingEfficiency); 1238 float turnComponent = rollComponents.Y * rollComponents.Y * m_bankingEfficiency;
1163 if (m_bankingEfficiency < 0) 1239 // Keep the sign
1164 effSquared *= -1; //Keep the negative! 1240 if (rollComponents.Y < 0f)
1241 turnComponent = -turnComponent;
1165 1242
1166 float mix = Math.Abs(m_bankingMix); 1243 // TODO: there must be a better computation of the banking force.
1167 // TODO: Must include reference frame. 1244 float bankingTurnForce = turnComponent;
1168 float forwardSpeed = VehicleVelocity.X;
1169 1245
1170 if (!Prim.IsColliding && forwardSpeed > mix) 1246 // actual error = static turn error + dynamic turn error
1171 { 1247 float mixedBankingError = bankingTurnForce * (1f - m_bankingMix) + bankingTurnForce * m_bankingMix * VehicleForwardSpeed;
1172 computedBanking.X = ClampInRange(-3f, turningFactor * (effSquared * mult), 3f); 1248 // TODO: the banking effect should not go to infinity but what to limit it to?
1173 } 1249 mixedBankingError = ClampInRange(-20f, mixedBankingError, 20f);
1174 1250
1175 // 'computedBanking' is now how much banking that should be happening. 1251 // Build the force vector to change rotation from what it is to what it should be
1176 ret = computedBanking - m_lastBanking; 1252 ret.Z = -mixedBankingError;
1177 1253
1178 // Scale the correction by timescale and efficiency 1254 // Don't do it all at once.
1179 ret /= m_bankingTimescale * m_bankingEfficiency; 1255 ret /= m_bankingTimescale;
1180 1256
1181 VDetailLog("{0}, MoveAngular,Banking,computedB={1},lastB={2},bEff={3},effSq={4},mult={5},mix={6},banking={7}", 1257 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},turnComp={3},bankErr={4},mixedBankErr={5},ret={6}",
1182 Prim.LocalID, computedBanking, m_lastBanking, m_bankingEfficiency, effSquared, mult, mix, ret); 1258 Prim.LocalID, rollComponents, VehicleForwardSpeed, turnComponent, bankingTurnForce, mixedBankingError, ret);
1183 } 1259 }
1184 m_lastBanking = computedBanking;
1185 return ret; 1260 return ret;
1186 } 1261 }
1187 1262
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
index 663b6f4..390c2f9 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
@@ -1,191 +1,185 @@
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 copyrightD 9 * * Redistributions in binary form must reproduce the above copyrightD
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 */
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Text; 29using System.Text;
30using System.Reflection; 30using System.Reflection;
31using Nini.Config; 31using Nini.Config;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35 35
36public struct MaterialAttributes 36public struct MaterialAttributes
37{ 37{
38 // Material type values that correspond with definitions for LSL 38 // Material type values that correspond with definitions for LSL
39 public enum Material : int 39 public enum Material : int
40 { 40 {
41 Stone = 0, 41 Stone = 0,
42 Metal, 42 Metal,
43 Glass, 43 Glass,
44 Wood, 44 Wood,
45 Flesh, 45 Flesh,
46 Plastic, 46 Plastic,
47 Rubber, 47 Rubber,
48 Light, 48 Light,
49 // Hereafter are BulletSim additions 49 // Hereafter are BulletSim additions
50 Avatar, 50 Avatar,
51 NumberOfTypes // the count of types in the enum. 51 NumberOfTypes // the count of types in the enum.
52 } 52 }
53 // Names must be in the order of the above enum. 53 // Names must be in the order of the above enum.
54 public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood", 54 public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
55 "Flesh", "Plastic", "Rubber", "Light", "Avatar" }; 55 "Flesh", "Plastic", "Rubber", "Light", "Avatar" };
56 public static string[] MaterialAttribs = { "Density", "Friction", "Restitution", 56 public static string[] MaterialAttribs = { "Density", "Friction", "Restitution"};
57 "ccdMotionThreshold", "ccdSweptSphereRadius" }; 57
58 58 public MaterialAttributes(string t, float d, float f, float r)
59 public MaterialAttributes(string t, float d, float f, float r, float ccdM, float ccdS) 59 {
60 { 60 type = t;
61 type = t; 61 density = d;
62 density = d; 62 friction = f;
63 friction = f; 63 restitution = r;
64 restitution = r; 64 }
65 ccdMotionThreshold = ccdM; 65 public string type;
66 ccdSweptSphereRadius = ccdS; 66 public float density;
67 } 67 public float friction;
68 public string type; 68 public float restitution;
69 public float density; 69}
70 public float friction; 70
71 public float restitution; 71public static class BSMaterials
72 public float ccdMotionThreshold; 72{
73 public float ccdSweptSphereRadius; 73 public static MaterialAttributes[] Attributes;
74} 74
75 75 static BSMaterials()
76public static class BSMaterials 76 {
77{ 77 // Attribute sets for both the non-physical and physical instances of materials.
78 public static MaterialAttributes[] Attributes; 78 Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2];
79 79 }
80 static BSMaterials() 80
81 { 81 // This is where all the default material attributes are defined.
82 // Attribute sets for both the non-physical and physical instances of materials. 82 public static void InitializeFromDefaults(ConfigurationParameters parms)
83 Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2]; 83 {
84 } 84 // Values from http://wiki.secondlife.com/wiki/PRIM_MATERIAL
85 85 // public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
86 // This is where all the default material attributes are defined. 86 // "Flesh", "Plastic", "Rubber", "Light", "Avatar" };
87 public static void InitializeFromDefaults(ConfigurationParameters parms) 87 float dFriction = parms.defaultFriction;
88 { 88 float dRestitution = parms.defaultRestitution;
89 // public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood", 89 float dDensity = parms.defaultDensity;
90 // "Flesh", "Plastic", "Rubber", "Light", "Avatar" }; 90 Attributes[(int)MaterialAttributes.Material.Stone] =
91 float dFriction = parms.defaultFriction; 91 new MaterialAttributes("stone",dDensity, 0.8f, 0.4f);
92 float dRestitution = parms.defaultRestitution; 92 Attributes[(int)MaterialAttributes.Material.Metal] =
93 float dDensity = parms.defaultDensity; 93 new MaterialAttributes("metal",dDensity, 0.3f, 0.4f);
94 float dCcdM = parms.ccdMotionThreshold; 94 Attributes[(int)MaterialAttributes.Material.Glass] =
95 float dCcdS = parms.ccdSweptSphereRadius; 95 new MaterialAttributes("glass",dDensity, 0.2f, 0.7f);
96 Attributes[(int)MaterialAttributes.Material.Stone] = 96 Attributes[(int)MaterialAttributes.Material.Wood] =
97 new MaterialAttributes("stone",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 97 new MaterialAttributes("wood",dDensity, 0.6f, 0.5f);
98 Attributes[(int)MaterialAttributes.Material.Metal] = 98 Attributes[(int)MaterialAttributes.Material.Flesh] =
99 new MaterialAttributes("metal",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 99 new MaterialAttributes("flesh",dDensity, 0.9f, 0.3f);
100 Attributes[(int)MaterialAttributes.Material.Glass] = 100 Attributes[(int)MaterialAttributes.Material.Plastic] =
101 new MaterialAttributes("glass",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 101 new MaterialAttributes("plastic",dDensity, 0.4f, 0.7f);
102 Attributes[(int)MaterialAttributes.Material.Wood] = 102 Attributes[(int)MaterialAttributes.Material.Rubber] =
103 new MaterialAttributes("wood",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 103 new MaterialAttributes("rubber",dDensity, 0.9f, 0.9f);
104 Attributes[(int)MaterialAttributes.Material.Flesh] = 104 Attributes[(int)MaterialAttributes.Material.Light] =
105 new MaterialAttributes("flesh",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 105 new MaterialAttributes("light",dDensity, dFriction, dRestitution);
106 Attributes[(int)MaterialAttributes.Material.Plastic] = 106 Attributes[(int)MaterialAttributes.Material.Avatar] =
107 new MaterialAttributes("plastic",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 107 new MaterialAttributes("avatar",60f, 0.2f, 0f);
108 Attributes[(int)MaterialAttributes.Material.Rubber] = 108
109 new MaterialAttributes("rubber",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 109 Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] =
110 Attributes[(int)MaterialAttributes.Material.Light] = 110 new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f);
111 new MaterialAttributes("light",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 111 Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] =
112 Attributes[(int)MaterialAttributes.Material.Avatar] = 112 new MaterialAttributes("metalPhysical",dDensity, 0.8f, 0.4f);
113 new MaterialAttributes("avatar",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 113 Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] =
114 114 new MaterialAttributes("glassPhysical",dDensity, 0.8f, 0.7f);
115 Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] = 115 Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] =
116 new MaterialAttributes("stonePhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 116 new MaterialAttributes("woodPhysical",dDensity, 0.8f, 0.5f);
117 Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] = 117 Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] =
118 new MaterialAttributes("metalPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 118 new MaterialAttributes("fleshPhysical",dDensity, 0.8f, 0.3f);
119 Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] = 119 Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] =
120 new MaterialAttributes("glassPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 120 new MaterialAttributes("plasticPhysical",dDensity, 0.8f, 0.7f);
121 Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] = 121 Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] =
122 new MaterialAttributes("woodPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 122 new MaterialAttributes("rubberPhysical",dDensity, 0.8f, 0.9f);
123 Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] = 123 Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] =
124 new MaterialAttributes("fleshPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 124 new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution);
125 Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] = 125 Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] =
126 new MaterialAttributes("plasticPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 126 new MaterialAttributes("avatarPhysical",60f, 0.2f, 0f);
127 Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] = 127 }
128 new MaterialAttributes("rubberPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 128
129 Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] = 129 // Under the [BulletSim] section, one can change the individual material
130 new MaterialAttributes("lightPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 130 // attribute values. The format of the configuration parameter is:
131 Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] = 131 // <materialName><Attribute>["Physical"] = floatValue
132 new MaterialAttributes("avatarPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS); 132 // For instance:
133 } 133 // [BulletSim]
134 134 // StoneFriction = 0.2
135 // Under the [BulletSim] section, one can change the individual material 135 // FleshRestitutionPhysical = 0.8
136 // attribute values. The format of the configuration parameter is: 136 // Materials can have different parameters for their static and
137 // <materialName><Attribute>["Physical"] = floatValue 137 // physical instantiations. When setting the non-physical value,
138 // For instance: 138 // both values are changed. Setting the physical value only changes
139 // [BulletSim] 139 // the physical value.
140 // StoneFriction = 0.2 140 public static void InitializefromParameters(IConfig pConfig)
141 // FleshRestitutionPhysical = 0.8 141 {
142 // Materials can have different parameters for their static and 142 int matType = 0;
143 // physical instantiations. When setting the non-physical value, 143 foreach (string matName in MaterialAttributes.MaterialNames)
144 // both values are changed. Setting the physical value only changes 144 {
145 // the physical value. 145 foreach (string attribName in MaterialAttributes.MaterialAttribs)
146 public static void InitializefromParameters(IConfig pConfig) 146 {
147 { 147 string paramName = matName + attribName;
148 int matType = 0; 148 if (pConfig.Contains(paramName))
149 foreach (string matName in MaterialAttributes.MaterialNames) 149 {
150 { 150 float paramValue = pConfig.GetFloat(paramName);
151 foreach (string attribName in MaterialAttributes.MaterialAttribs) 151 SetAttributeValue(matType, attribName, paramValue);
152 { 152 // set the physical value also
153 string paramName = matName + attribName; 153 SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
154 if (pConfig.Contains(paramName)) 154 }
155 { 155 paramName += "Physical";
156 float paramValue = pConfig.GetFloat(paramName); 156 if (pConfig.Contains(paramName))
157 SetAttributeValue(matType, attribName, paramValue); 157 {
158 // set the physical value also 158 float paramValue = pConfig.GetFloat(paramName);
159 SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue); 159 SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
160 } 160 }
161 paramName += "Physical"; 161 }
162 if (pConfig.Contains(paramName)) 162 matType++;
163 { 163 }
164 float paramValue = pConfig.GetFloat(paramName); 164 }
165 SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue); 165
166 } 166 private static void SetAttributeValue(int matType, string attribName, float val)
167 } 167 {
168 matType++; 168 MaterialAttributes thisAttrib = Attributes[matType];
169 } 169 FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName);
170 } 170 if (fieldInfo != null)
171 171 {
172 private static void SetAttributeValue(int matType, string attribName, float val) 172 fieldInfo.SetValue(thisAttrib, val);
173 { 173 Attributes[matType] = thisAttrib;
174 MaterialAttributes thisAttrib = Attributes[matType]; 174 }
175 FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName); 175 }
176 if (fieldInfo != null) 176
177 { 177 public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical)
178 fieldInfo.SetValue(thisAttrib, val); 178 {
179 Attributes[matType] = thisAttrib; 179 int ind = (int)type;
180 } 180 if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes;
181 } 181 return Attributes[ind];
182 182 }
183 public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical) 183
184 { 184}
185 int ind = (int)type; 185}
186 if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes;
187 return Attributes[ind];
188 }
189
190}
191}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index ea1f71a..62aaf80 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -1010,6 +1010,9 @@ public sealed class BSPrim : BSPhysObject
1010 }); 1010 });
1011 } 1011 }
1012 // A torque impulse. 1012 // A torque impulse.
1013 // ApplyTorqueImpulse adds torque directly to the angularVelocity.
1014 // AddAngularForce accumulates the force and applied it to the angular velocity all at once.
1015 // Computed as: angularVelocity += impulse * inertia;
1013 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) 1016 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
1014 { 1017 {
1015 OMV.Vector3 applyImpulse = impulse; 1018 OMV.Vector3 applyImpulse = impulse;
@@ -1396,7 +1399,7 @@ public sealed class BSPrim : BSPhysObject
1396 _rotationalVelocity = entprop.RotationalVelocity; 1399 _rotationalVelocity = entprop.RotationalVelocity;
1397 1400
1398 // The sanity check can change the velocity and/or position. 1401 // The sanity check can change the velocity and/or position.
1399 if (PositionSanityCheck(true)) 1402 if (IsPhysical && PositionSanityCheck(true))
1400 { 1403 {
1401 entprop.Position = _position; 1404 entprop.Position = _position;
1402 entprop.Velocity = _velocity; 1405 entprop.Velocity = _velocity;
@@ -1410,8 +1413,6 @@ public sealed class BSPrim : BSPhysObject
1410 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", 1413 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
1411 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); 1414 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
1412 1415
1413 // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG
1414
1415 base.RequestPhysicsterseUpdate(); 1416 base.RequestPhysicsterseUpdate();
1416 } 1417 }
1417 /* 1418 /*
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 2d7a4a0..a5e5754 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -65,9 +65,16 @@ public sealed class BSShapeCollection : IDisposable
65 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>(); 65 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
66 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>(); 66 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
67 67
68 private bool DDetail = false;
69
68 public BSShapeCollection(BSScene physScene) 70 public BSShapeCollection(BSScene physScene)
69 { 71 {
70 PhysicsScene = physScene; 72 PhysicsScene = physScene;
73 // Set the next to 'true' for very detailed shape update detailed logging (detailed details?)
74 // While detailed debugging is still active, this is better than commenting out all the
75 // DetailLog statements. When debugging slows down, this and the protected logging
76 // statements can be commented/removed.
77 DDetail = true;
71 } 78 }
72 79
73 public void Dispose() 80 public void Dispose()
@@ -126,13 +133,13 @@ public sealed class BSShapeCollection : IDisposable
126 { 133 {
127 lock (m_collectionActivityLock) 134 lock (m_collectionActivityLock)
128 { 135 {
129 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); 136 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
130 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() 137 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate()
131 { 138 {
132 if (!BulletSimAPI.IsInWorld2(body.ptr)) 139 if (!BulletSimAPI.IsInWorld2(body.ptr))
133 { 140 {
134 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); 141 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr);
135 DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); 142 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
136 } 143 }
137 }); 144 });
138 } 145 }
@@ -149,7 +156,7 @@ public sealed class BSShapeCollection : IDisposable
149 { 156 {
150 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() 157 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate()
151 { 158 {
152 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", 159 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}",
153 body.ID, body, inTaintTime); 160 body.ID, body, inTaintTime);
154 // If the caller needs to know the old body is going away, pass the event up. 161 // If the caller needs to know the old body is going away, pass the event up.
155 if (bodyCallback != null) bodyCallback(body); 162 if (bodyCallback != null) bodyCallback(body);
@@ -157,7 +164,7 @@ public sealed class BSShapeCollection : IDisposable
157 if (BulletSimAPI.IsInWorld2(body.ptr)) 164 if (BulletSimAPI.IsInWorld2(body.ptr))
158 { 165 {
159 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); 166 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
160 DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); 167 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
161 } 168 }
162 169
163 // Zero any reference to the shape so it is not freed when the body is deleted. 170 // Zero any reference to the shape so it is not freed when the body is deleted.
@@ -184,7 +191,7 @@ public sealed class BSShapeCollection : IDisposable
184 { 191 {
185 // There is an existing instance of this mesh. 192 // There is an existing instance of this mesh.
186 meshDesc.referenceCount++; 193 meshDesc.referenceCount++;
187 DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", 194 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
188 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); 195 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
189 } 196 }
190 else 197 else
@@ -194,7 +201,7 @@ public sealed class BSShapeCollection : IDisposable
194 meshDesc.shapeKey = shape.shapeKey; 201 meshDesc.shapeKey = shape.shapeKey;
195 // We keep a reference to the underlying IMesh data so a hull can be built 202 // We keep a reference to the underlying IMesh data so a hull can be built
196 meshDesc.referenceCount = 1; 203 meshDesc.referenceCount = 1;
197 DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", 204 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
198 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); 205 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
199 ret = true; 206 ret = true;
200 } 207 }
@@ -207,7 +214,7 @@ public sealed class BSShapeCollection : IDisposable
207 { 214 {
208 // There is an existing instance of this hull. 215 // There is an existing instance of this hull.
209 hullDesc.referenceCount++; 216 hullDesc.referenceCount++;
210 DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", 217 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
211 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); 218 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
212 } 219 }
213 else 220 else
@@ -216,7 +223,7 @@ public sealed class BSShapeCollection : IDisposable
216 hullDesc.ptr = shape.ptr; 223 hullDesc.ptr = shape.ptr;
217 hullDesc.shapeKey = shape.shapeKey; 224 hullDesc.shapeKey = shape.shapeKey;
218 hullDesc.referenceCount = 1; 225 hullDesc.referenceCount = 1;
219 DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", 226 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
220 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); 227 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
221 ret = true; 228 ret = true;
222 229
@@ -246,7 +253,7 @@ public sealed class BSShapeCollection : IDisposable
246 if (shape.isNativeShape) 253 if (shape.isNativeShape)
247 { 254 {
248 // Native shapes are not tracked and are released immediately 255 // Native shapes are not tracked and are released immediately
249 DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", 256 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
250 BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); 257 BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime);
251 if (shapeCallback != null) shapeCallback(shape); 258 if (shapeCallback != null) shapeCallback(shape);
252 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); 259 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
@@ -286,7 +293,7 @@ public sealed class BSShapeCollection : IDisposable
286 if (shapeCallback != null) shapeCallback(shape); 293 if (shapeCallback != null) shapeCallback(shape);
287 meshDesc.lastReferenced = System.DateTime.Now; 294 meshDesc.lastReferenced = System.DateTime.Now;
288 Meshes[shape.shapeKey] = meshDesc; 295 Meshes[shape.shapeKey] = meshDesc;
289 DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}", 296 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
290 BSScene.DetailLogZero, shape, meshDesc.referenceCount); 297 BSScene.DetailLogZero, shape, meshDesc.referenceCount);
291 298
292 } 299 }
@@ -307,7 +314,7 @@ public sealed class BSShapeCollection : IDisposable
307 314
308 hullDesc.lastReferenced = System.DateTime.Now; 315 hullDesc.lastReferenced = System.DateTime.Now;
309 Hulls[shape.shapeKey] = hullDesc; 316 Hulls[shape.shapeKey] = hullDesc;
310 DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}", 317 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
311 BSScene.DetailLogZero, shape, hullDesc.referenceCount); 318 BSScene.DetailLogZero, shape, hullDesc.referenceCount);
312 } 319 }
313 } 320 }
@@ -325,13 +332,13 @@ public sealed class BSShapeCollection : IDisposable
325 // Failed the sanity check!! 332 // Failed the sanity check!!
326 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", 333 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
327 LogHeader, shape.type, shape.ptr.ToString("X")); 334 LogHeader, shape.type, shape.ptr.ToString("X"));
328 DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", 335 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
329 BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X")); 336 BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X"));
330 return; 337 return;
331 } 338 }
332 339
333 int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); 340 int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr);
334 DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren); 341 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
335 342
336 for (int ii = numChildren - 1; ii >= 0; ii--) 343 for (int ii = numChildren - 1; ii >= 0; ii--)
337 { 344 {
@@ -379,7 +386,7 @@ public sealed class BSShapeCollection : IDisposable
379 } 386 }
380 } 387 }
381 388
382 DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); 389 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
383 390
384 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN) 391 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
385 { 392 {
@@ -410,7 +417,7 @@ public sealed class BSShapeCollection : IDisposable
410 // an avatar capsule is close to a native shape (it is not shared) 417 // an avatar capsule is close to a native shape (it is not shared)
411 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, 418 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE,
412 FixedShapeKey.KEY_CAPSULE, shapeCallback); 419 FixedShapeKey.KEY_CAPSULE, shapeCallback);
413 DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); 420 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
414 ret = true; 421 ret = true;
415 haveShape = true; 422 haveShape = true;
416 } 423 }
@@ -420,7 +427,7 @@ public sealed class BSShapeCollection : IDisposable
420 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) 427 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
421 { 428 {
422 ret = GetReferenceToCompoundShape(prim, shapeCallback); 429 ret = GetReferenceToCompoundShape(prim, shapeCallback);
423 DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); 430 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
424 haveShape = true; 431 haveShape = true;
425 } 432 }
426 433
@@ -465,7 +472,7 @@ public sealed class BSShapeCollection : IDisposable
465 { 472 {
466 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, 473 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE,
467 FixedShapeKey.KEY_SPHERE, shapeCallback); 474 FixedShapeKey.KEY_SPHERE, shapeCallback);
468 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", 475 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
469 prim.LocalID, forceRebuild, prim.PhysShape); 476 prim.LocalID, forceRebuild, prim.PhysShape);
470 } 477 }
471 } 478 }
@@ -479,7 +486,7 @@ public sealed class BSShapeCollection : IDisposable
479 { 486 {
480 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, 487 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX,
481 FixedShapeKey.KEY_BOX, shapeCallback); 488 FixedShapeKey.KEY_BOX, shapeCallback);
482 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", 489 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
483 prim.LocalID, forceRebuild, prim.PhysShape); 490 prim.LocalID, forceRebuild, prim.PhysShape);
484 } 491 }
485 } 492 }
@@ -504,13 +511,13 @@ public sealed class BSShapeCollection : IDisposable
504 { 511 {
505 // Update prim.BSShape to reference a hull of this shape. 512 // Update prim.BSShape to reference a hull of this shape.
506 ret = GetReferenceToHull(prim,shapeCallback); 513 ret = GetReferenceToHull(prim,shapeCallback);
507 DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", 514 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
508 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); 515 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
509 } 516 }
510 else 517 else
511 { 518 {
512 ret = GetReferenceToMesh(prim, shapeCallback); 519 ret = GetReferenceToMesh(prim, shapeCallback);
513 DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", 520 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
514 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); 521 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
515 } 522 }
516 return ret; 523 return ret;
@@ -528,7 +535,7 @@ public sealed class BSShapeCollection : IDisposable
528 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); 535 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
529 536
530 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. 537 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
531 DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", 538 if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
532 prim.LocalID, newShape, prim.Scale); 539 prim.LocalID, newShape, prim.Scale);
533 540
534 prim.PhysShape = newShape; 541 prim.PhysShape = newShape;
@@ -554,7 +561,7 @@ public sealed class BSShapeCollection : IDisposable
554 newShape = new BulletShape( 561 newShape = new BulletShape(
555 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) 562 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale)
556 , shapeType); 563 , shapeType);
557 DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); 564 if (DDetail) DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
558 } 565 }
559 else 566 else
560 { 567 {
@@ -589,7 +596,7 @@ public sealed class BSShapeCollection : IDisposable
589 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH) 596 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH)
590 return false; 597 return false;
591 598
592 DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", 599 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}",
593 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); 600 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
594 601
595 // Since we're recreating new, get rid of the reference to the previous shape 602 // Since we're recreating new, get rid of the reference to the previous shape
@@ -662,7 +669,7 @@ public sealed class BSShapeCollection : IDisposable
662 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL) 669 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL)
663 return false; 670 return false;
664 671
665 DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", 672 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
666 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); 673 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
667 674
668 // Remove usage of the previous shape. 675 // Remove usage of the previous shape.
@@ -808,7 +815,7 @@ public sealed class BSShapeCollection : IDisposable
808 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. 815 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
809 CreateGeomMeshOrHull(prim, shapeCallback); 816 CreateGeomMeshOrHull(prim, shapeCallback);
810 BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity); 817 BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity);
811 DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", 818 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
812 prim.LocalID, cShape, prim.PhysShape); 819 prim.LocalID, cShape, prim.PhysShape);
813 820
814 prim.PhysShape = cShape; 821 prim.PhysShape = cShape;
@@ -935,13 +942,13 @@ public sealed class BSShapeCollection : IDisposable
935 { 942 {
936 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, 943 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr,
937 prim.LocalID, prim.RawPosition, prim.RawOrientation); 944 prim.LocalID, prim.RawPosition, prim.RawOrientation);
938 DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); 945 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
939 } 946 }
940 else 947 else
941 { 948 {
942 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, 949 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
943 prim.LocalID, prim.RawPosition, prim.RawOrientation); 950 prim.LocalID, prim.RawPosition, prim.RawOrientation);
944 DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); 951 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
945 } 952 }
946 aBody = new BulletBody(prim.LocalID, bodyPtr); 953 aBody = new BulletBody(prim.LocalID, bodyPtr);
947 954
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index a5acfd1..2671995 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -360,6 +360,7 @@ public enum CollisionFlags : uint
360 // Following used by BulletSim to control collisions and updates 360 // Following used by BulletSim to control collisions and updates
361 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, 361 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
362 BS_FLOATS_ON_WATER = 1 << 11, 362 BS_FLOATS_ON_WATER = 1 << 11,
363 BS_VEHICLE_COLLISIONS = 1 << 12,
363 BS_NONE = 0, 364 BS_NONE = 0,
364 BS_ALL = 0xFFFFFFFF, 365 BS_ALL = 0xFFFFFFFF,
365 366
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index 68f25fc..d51003c 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -6,14 +6,34 @@ CRASHES
6 Causes many errors. Doesn't stop after first error with box shape. 6 Causes many errors. Doesn't stop after first error with box shape.
7 Eventually crashes when deleting the object. 7 Eventually crashes when deleting the object.
8 8
9BULLETSIM TODO LIST: 9VEHICLES TODO LIST:
10================================================= 10=================================================
11Neb car jiggling left and right 11Neb car jiggling left and right
12 Happens on terrain and any other mesh object. Flat cubes are much smoother.
12Vehicles (Move smoothly) 13Vehicles (Move smoothly)
13Light cycle falling over when driving 14Add vehicle collisions so IsColliding is properly reported.
14Light cycle not banking 15 Needed for banking, limitMotorUp, movementLimiting, ...
15Do single prim vehicles don't seem to properly vehiclize. 16Some vehicles should not be able to turn if no speed or off ground.
16Gun sending shooter flying 17For limitMotorUp, use raycast down to find if vehicle is in the air.
18Implement function efficiency for lineaar and angular motion.
19Should vehicle angular/linear movement friction happen after all the components
20 or does it only apply to the basic movement?
21After getting off a vehicle, the root prim is phantom (can be walked through)
22 Need to force a position update for the root prim after compound shape destruction
23Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
24Implement referenceFrame for all the motion routines.
25Cannot edit/move a vehicle being ridden: it jumps back to the origional position.
26
27BULLETSIM TODO LIST:
28=================================================
29Disable activity of passive linkset children.
30 Since the linkset is a compound object, the old prims are left lying
31 around and need to be phantomized so they don't collide, ...
32Scenes with hundred of thousands of static objects take a lot of physics CPU time.
33BSPrim.Force should set a continious force on the prim. The force should be
34 applied each tick. Some limits?
35Single prim vehicles don't seem to properly vehiclize.
36Gun sending shooter flying.
17Collision margin (gap between physical objects lying on each other) 37Collision margin (gap between physical objects lying on each other)
18Boundry checking (crashes related to crossing boundry) 38Boundry checking (crashes related to crossing boundry)
19 Add check for border edge position for avatars and objects. 39 Add check for border edge position for avatars and objects.
@@ -28,10 +48,11 @@ Small physical objects do not interact correctly
28Add material type linkage and input all the material property definitions. 48Add material type linkage and input all the material property definitions.
29 Skeleton classes and table are in the sources but are not filled or used. 49 Skeleton classes and table are in the sources but are not filled or used.
30Add PID motor for avatar movement (slow to stop, ...) 50Add PID motor for avatar movement (slow to stop, ...)
31Implement function efficiency for lineaar and angular motion. 51setForce should set a constant force. Different than AddImpulse.
52Implement raycast.
53Implement ShapeCollection.Dispose()
54Implement water as a plain so raycasting and collisions can happen with same.
32 55
33After getting off a vehicle, the root prim is phantom (can be walked through)
34 Need to force a position update for the root prim after compound shape destruction
35Find/remove avatar collision with ID=0. 56Find/remove avatar collision with ID=0.
36Test avatar walking up stairs. How does compare with SL. 57Test avatar walking up stairs. How does compare with SL.
37 Radius of the capsule affects ability to climb edges. 58 Radius of the capsule affects ability to climb edges.
@@ -39,19 +60,16 @@ Tune terrain/object friction to be closer to SL.
39Debounce avatar contact so legs don't keep folding up when standing. 60Debounce avatar contact so legs don't keep folding up when standing.
40Implement LSL physics controls. Like STATUS_ROTATE_X. 61Implement LSL physics controls. Like STATUS_ROTATE_X.
41Add border extensions to terrain to help region crossings and objects leaving region. 62Add border extensions to terrain to help region crossings and objects leaving region.
42Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
43 63
44Speed up creation of large physical linksets 64Speed up creation of large physical linksets
45 For instance, sitting in Neb's car (130 prims) takes several seconds to become physical 65 For instance, sitting in Neb's car (130 prims) takes several seconds to become physical
46Performance test with lots of avatars. Can BulletSim support a thousand? 66Performance test with lots of avatars. Can BulletSim support a thousand?
47Optimize collisions in C++: only send up to the object subscribed to collisions. 67Optimize collisions in C++: only send up to the object subscribed to collisions.
48 Use collision subscription and remove the collsion(A,B) and collision(B,A) 68 Use collision subscription and remove the collsion(A,B) and collision(B,A)
49Check wheter SimMotionState needs large if statement (see TODO). 69Check whether SimMotionState needs large if statement (see TODO).
50 70
51Implement 'top colliders' info. 71Implement 'top colliders' info.
52Avatar jump 72Avatar jump
53Implement meshes or just verify that they work.
54Do prim hash codes work for sculpties and meshes?
55Performance measurement and changes to make quicker. 73Performance measurement and changes to make quicker.
56Implement detailed physics stats (GetStats()). 74Implement detailed physics stats (GetStats()).
57 75
@@ -67,8 +85,6 @@ Performance of closures and delegates for taint processing
67Is there are more efficient method of implementing pre and post step actions? 85Is there are more efficient method of implementing pre and post step actions?
68 See http://www.codeproject.com/Articles/29922/Weak-Events-in-C 86 See http://www.codeproject.com/Articles/29922/Weak-Events-in-C
69 87
70Package Bullet source mods for Bullet internal stats output
71
72Physics Arena central pyramid: why is one side permiable? 88Physics Arena central pyramid: why is one side permiable?
73 89
74INTERNAL IMPROVEMENT/CLEANUP 90INTERNAL IMPROVEMENT/CLEANUP
@@ -85,33 +101,42 @@ Complete implemention of preStepActions
85 Replace vehicle step call with prestep event. 101 Replace vehicle step call with prestep event.
86 Is there a need for postStepActions? postStepTaints? 102 Is there a need for postStepActions? postStepTaints?
87Implement linkset by setting position of children when root updated. (LinksetManual) 103Implement linkset by setting position of children when root updated. (LinksetManual)
104 Linkset implementation using manual prim movement.
88LinkablePrim class? Would that simplify/centralize the linkset logic? 105LinkablePrim class? Would that simplify/centralize the linkset logic?
89Linkset implementation using manual prim movement.
90Linkset implementation using compound shapes.
91 Compound shapes will need the LocalID in the shapes and collision
92 processing to get it from there.
93BSScene.UpdateParameterSet() is broken. How to set params on objects? 106BSScene.UpdateParameterSet() is broken. How to set params on objects?
94Remove HeightmapInfo from terrain specification. 107Remove HeightmapInfo from terrain specification.
95 Since C++ code does not need terrain height, this structure et al are not needed. 108 Since C++ code does not need terrain height, this structure et al are not needed.
96Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will 109Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will
97 bob at the water level. BSPrim.PositionSanityCheck(). 110 bob at the water level. BSPrim.PositionSanityCheck().
98 111
112THREADING
113=================================================
114Do taint action immediately if not actually executing Bullet.
115 Add lock around Bullet execution and just do taint actions if simulation is not happening.
116
99DONE DONE DONE DONE 117DONE DONE DONE DONE
100================================================= 118=================================================
101Cleanup code in BSDynamics by using motors. 119Cleanup code in BSDynamics by using motors. (Resolution: started)
102Consider implementing terrain with a mesh rather than heightmap. 120Consider implementing terrain with a mesh rather than heightmap. (Resolution: done)
103 Would have better and adjustable resolution. 121 Would have better and adjustable resolution.
104NOTDONE: Build terrain mesh so heighmap is height of the center of the square meter. 122Build terrain mesh so heighmap is height of the center of the square meter.
105 SL and ODE define meter square as being at one corner with one diagional. 123 Resolution: NOT DONE: SL and ODE define meter square as being at one corner with one diagional.
106Terrain as mesh. 124Terrain as mesh. (Resolution: done)
107How are static linksets seen by the physics engine? 125How are static linksets seen by the physics engine?
108 A: they are not linked in physics. When moved, all the children are repositioned. 126 Resolution: they are not linked in physics. When moved, all the children are repositioned.
109Remember to remove BSScene.DetailLog Refresh call. 127Convert BSCharacter to use all API2 (Resolution: done)
110Convert BSCharacter to use all API2
111Avatar pushing difficult (too heavy?) 128Avatar pushing difficult (too heavy?)
112Use asset service passed to BulletSim to get sculptie bodies, etc. 129Use asset service passed to BulletSim to get sculptie bodies, etc. (Resolution: done)
113Vehicles (fix bouncing on terrain) 130Remove old code in DLL (all non-API2 stuff). (Resolution: done)
114Remove old code in DLL (all non-API2 stuff). 131Measurements of mega-physical prim performance (with graph) (Resolution: done, email)
115Measurements of mega-physical prim performance (with graph)
116Debug Bullet internal stats output (why is timing all wrong?) 132Debug Bullet internal stats output (why is timing all wrong?)
117 Bullet stats logging only works with a single instance of Bullet (one region). \ No newline at end of file 133 Resolution: Bullet stats logging only works with a single instance of Bullet (one region).
134Implement meshes or just verify that they work. (Resolution: they do!)
135Do prim hash codes work for sculpties and meshes? (Resolution: yes)
136Linkset implementation using compound shapes. (Resolution: implemented LinksetCompound)
137 Compound shapes will need the LocalID in the shapes and collision
138 processing to get it from there.
139Light cycle falling over when driving (Resolution: implemented VerticalAttractor)
140Light cycle not banking (Resolution: It doesn't. Banking is roll adding yaw.)
141Package Bullet source mods for Bullet internal stats output
142 (Resolution: move code into WorldData.h rather than relying on patches) \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
index b04f6b6..0cef550 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -114,6 +114,16 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
114 UUID AssetID { get; } 114 UUID AssetID { get; }
115 Queue EventQueue { get; } 115 Queue EventQueue { get; }
116 116
117 /// <summary>
118 /// Number of events queued for processing.
119 /// </summary>
120 long EventsQueued { get; }
121
122 /// <summary>
123 /// Number of events processed by this script instance.
124 /// </summary>
125 long EventsProcessed { get; }
126
117 void ClearQueue(); 127 void ClearQueue();
118 int StartParam { get; set; } 128 int StartParam { get; set; }
119 129
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 771db0c..538cb8b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -174,6 +174,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
174 174
175 public Queue EventQueue { get; private set; } 175 public Queue EventQueue { get; private set; }
176 176
177 public long EventsQueued
178 {
179 get
180 {
181 lock (EventQueue)
182 return EventQueue.Count;
183 }
184 }
185
186 public long EventsProcessed { get; private set; }
187
177 public int StartParam { get; set; } 188 public int StartParam { get; set; }
178 189
179 public TaskInventoryItem ScriptTask { get; private set; } 190 public TaskInventoryItem ScriptTask { get; private set; }
@@ -776,6 +787,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
776 ChatTypeEnum.DebugChannel, 2147483647, 787 ChatTypeEnum.DebugChannel, 2147483647,
777 part.AbsolutePosition, 788 part.AbsolutePosition,
778 part.Name, part.UUID, false); 789 part.Name, part.UUID, false);
790
791
792 m_log.DebugFormat(
793 "[SCRIPT INSTANCE]: Runtime error in script {0}, part {1} {2} at {3} in {4}, displayed error {5}, actual exception {6}",
794 ScriptName,
795 PrimName,
796 part.UUID,
797 part.AbsolutePosition,
798 part.ParentGroup.Scene.Name,
799 text.Replace("\n", "\\n"),
800 e.InnerException);
779 } 801 }
780 catch (Exception) 802 catch (Exception)
781 { 803 {
@@ -810,6 +832,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
810 // script engine to run the next event. 832 // script engine to run the next event.
811 lock (EventQueue) 833 lock (EventQueue)
812 { 834 {
835 EventsProcessed++;
836
813 if (EventQueue.Count > 0 && Running && !ShuttingDown) 837 if (EventQueue.Count > 0 && Running && !ShuttingDown)
814 { 838 {
815 m_CurrentWorkItem = Engine.QueueEventHandler(this); 839 m_CurrentWorkItem = Engine.QueueEventHandler(this);
@@ -1015,7 +1039,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1015 "({0}): {1}", scriptLine - 1, 1039 "({0}): {1}", scriptLine - 1,
1016 e.InnerException.Message); 1040 e.InnerException.Message);
1017 1041
1018 System.Console.WriteLine(e.ToString()+"\n");
1019 return message; 1042 return message;
1020 } 1043 }
1021 } 1044 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
index 2c9d9e8..cb7291a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
@@ -57,8 +57,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
57 protected XEngine.XEngine m_engine; 57 protected XEngine.XEngine m_engine;
58 58
59 [SetUp] 59 [SetUp]
60 public void SetUp() 60 public override void SetUp()
61 { 61 {
62 base.SetUp();
63
62 IConfigSource initConfigSource = new IniConfigSource(); 64 IConfigSource initConfigSource = new IniConfigSource();
63 IConfig config = initConfigSource.AddConfig("XEngine"); 65 IConfig config = initConfigSource.AddConfig("XEngine");
64 config.Set("Enabled", "true"); 66 config.Set("Enabled", "true");
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
index 57f19b9..d9b17d7 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
@@ -62,8 +62,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
62 protected XEngine.XEngine m_engine; 62 protected XEngine.XEngine m_engine;
63 63
64 [SetUp] 64 [SetUp]
65 public void SetUp() 65 public override void SetUp()
66 { 66 {
67 base.SetUp();
68
67 IConfigSource initConfigSource = new IniConfigSource(); 69 IConfigSource initConfigSource = new IniConfigSource();
68 IConfig config = initConfigSource.AddConfig("XEngine"); 70 IConfig config = initConfigSource.AddConfig("XEngine");
69 config.Set("Enabled", "true"); 71 config.Set("Enabled", "true");
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
index 182b07b..98017d8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
@@ -51,8 +51,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
51 private LSL_Api m_lslApi; 51 private LSL_Api m_lslApi;
52 52
53 [SetUp] 53 [SetUp]
54 public void SetUp() 54 public override void SetUp()
55 { 55 {
56 base.SetUp();
57
56 IConfigSource initConfigSource = new IniConfigSource(); 58 IConfigSource initConfigSource = new IniConfigSource();
57 IConfig config = initConfigSource.AddConfig("XEngine"); 59 IConfig config = initConfigSource.AddConfig("XEngine");
58 config.Set("Enabled", "true"); 60 config.Set("Enabled", "true");
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
index 213f33f..1381d2b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
@@ -57,8 +57,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
57 protected XEngine.XEngine m_engine; 57 protected XEngine.XEngine m_engine;
58 58
59 [SetUp] 59 [SetUp]
60 public void SetUp() 60 public override void SetUp()
61 { 61 {
62 base.SetUp();
63
62 IConfigSource initConfigSource = new IniConfigSource(); 64 IConfigSource initConfigSource = new IniConfigSource();
63 IConfig config = initConfigSource.AddConfig("XEngine"); 65 IConfig config = initConfigSource.AddConfig("XEngine");
64 config.Set("Enabled", "true"); 66 config.Set("Enabled", "true");
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
index b49bcc2..d6c82f1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
@@ -127,12 +127,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
127 OSSL_Api osslApi = new OSSL_Api(); 127 OSSL_Api osslApi = new OSSL_Api();
128 osslApi.Initialize(m_engine, so.RootPart, null); 128 osslApi.Initialize(m_engine, so.RootPart, null);
129 129
130 string npcRaw;
131 bool gotExpectedException = false; 130 bool gotExpectedException = false;
132 try 131 try
133 { 132 {
134 npcRaw 133 osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name");
135 = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name");
136 } 134 }
137 catch (ScriptException) 135 catch (ScriptException)
138 { 136 {
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 9f05666..05ba890 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.Diagnostics; //for [DebuggerNonUserCode] 31using System.Diagnostics; //for [DebuggerNonUserCode]
32using System.Globalization; 32using System.Globalization;
33using System.IO; 33using System.IO;
34using System.Linq;
34using System.Reflection; 35using System.Reflection;
35using System.Security; 36using System.Security;
36using System.Security.Policy; 37using System.Security.Policy;
@@ -445,9 +446,21 @@ namespace OpenSim.Region.ScriptEngine.XEngine
445 /// </summary> 446 /// </summary>
446 /// <param name="cmdparams"></param> 447 /// <param name="cmdparams"></param>
447 /// <param name="instance"></param> 448 /// <param name="instance"></param>
448 /// <returns>true if we're okay to proceed, false if not.</returns> 449 /// <param name="comparer">Basis on which to sort output. Can be null if no sort needs to take place</param>
449 private void HandleScriptsAction(string[] cmdparams, Action<IScriptInstance> action) 450 private void HandleScriptsAction(string[] cmdparams, Action<IScriptInstance> action)
450 { 451 {
452 HandleScriptsAction<object>(cmdparams, action, null);
453 }
454
455 /// <summary>
456 /// Parse the raw item id into a script instance from the command params if it's present.
457 /// </summary>
458 /// <param name="cmdparams"></param>
459 /// <param name="instance"></param>
460 /// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param>
461 private void HandleScriptsAction<TKey>(
462 string[] cmdparams, Action<IScriptInstance> action, Func<IScriptInstance, TKey> keySelector)
463 {
451 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) 464 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
452 return; 465 return;
453 466
@@ -458,7 +471,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
458 471
459 if (cmdparams.Length == 2) 472 if (cmdparams.Length == 2)
460 { 473 {
461 foreach (IScriptInstance instance in m_Scripts.Values) 474 IEnumerable<IScriptInstance> scripts = m_Scripts.Values;
475
476 if (keySelector != null)
477 scripts = scripts.OrderBy<IScriptInstance, TKey>(keySelector);
478
479 foreach (IScriptInstance instance in scripts)
462 action(instance); 480 action(instance);
463 481
464 return; 482 return;
@@ -505,9 +523,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
505 StringBuilder sb = new StringBuilder(); 523 StringBuilder sb = new StringBuilder();
506 sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName); 524 sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName);
507 525
526 long scriptsLoaded, eventsQueued = 0, eventsProcessed = 0;
527
508 lock (m_Scripts) 528 lock (m_Scripts)
509 sb.AppendFormat("Scripts loaded : {0}\n", m_Scripts.Count); 529 {
530 scriptsLoaded = m_Scripts.Count;
510 531
532 foreach (IScriptInstance si in m_Scripts.Values)
533 {
534 eventsQueued += si.EventsQueued;
535 eventsProcessed += si.EventsProcessed;
536 }
537 }
538
539 sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded);
511 sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count); 540 sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count);
512 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); 541 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count);
513 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads); 542 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads);
@@ -516,6 +545,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
516 sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads); 545 sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads);
517 sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks); 546 sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks);
518// sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count); 547// sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count);
548 sb.AppendFormat("Events queued : {0}\n", eventsQueued);
549 sb.AppendFormat("Events processed : {0}\n", eventsProcessed);
519 550
520 SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this); 551 SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this);
521 sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0); 552 sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0);
@@ -546,7 +577,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
546 } 577 }
547 } 578 }
548 579
549 HandleScriptsAction(cmdparams, HandleShowScript); 580 HandleScriptsAction<long>(cmdparams, HandleShowScript, si => si.EventsProcessed);
550 } 581 }
551 582
552 private void HandleShowScript(IScriptInstance instance) 583 private void HandleShowScript(IScriptInstance instance)
@@ -576,10 +607,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
576 607
577 sb.AppendFormat("Script name : {0}\n", instance.ScriptName); 608 sb.AppendFormat("Script name : {0}\n", instance.ScriptName);
578 sb.AppendFormat("Status : {0}\n", status); 609 sb.AppendFormat("Status : {0}\n", status);
579 610 sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued);
580 lock (eq) 611 sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed);
581 sb.AppendFormat("Queued events : {0}\n", eq.Count);
582
583 sb.AppendFormat("Item UUID : {0}\n", instance.ItemID); 612 sb.AppendFormat("Item UUID : {0}\n", instance.ItemID);
584 sb.AppendFormat("Containing part name: {0}\n", instance.PrimName); 613 sb.AppendFormat("Containing part name: {0}\n", instance.PrimName);
585 sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID); 614 sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID);
@@ -1089,8 +1118,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1089 1118
1090 string assembly = ""; 1119 string assembly = "";
1091 1120
1092 CultureInfo USCulture = new CultureInfo("en-US"); 1121 Culture.SetCurrentCulture();
1093 Thread.CurrentThread.CurrentCulture = USCulture;
1094 1122
1095 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap; 1123 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap;
1096 1124
@@ -1504,8 +1532,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1504 /// <returns></returns> 1532 /// <returns></returns>
1505 private object ProcessEventHandler(object parms) 1533 private object ProcessEventHandler(object parms)
1506 { 1534 {
1507 CultureInfo USCulture = new CultureInfo("en-US"); 1535 Culture.SetCurrentCulture();
1508 Thread.CurrentThread.CurrentCulture = USCulture;
1509 1536
1510 IScriptInstance instance = (ScriptInstance) parms; 1537 IScriptInstance instance = (ScriptInstance) parms;
1511 1538