diff options
author | Diva Canto | 2012-12-06 20:04:59 -0800 |
---|---|---|
committer | Diva Canto | 2012-12-06 20:04:59 -0800 |
commit | 3c9f8c9c46546da0944632b853313aa52f38cc00 (patch) | |
tree | 548bef5b08feb9e6df9e136de5e4a4fd4ca3c549 /OpenSim | |
parent | Trying to prevent old route of sending attachments, simulator version unknown... (diff) | |
parent | Merge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff) | |
download | opensim-SC-3c9f8c9c46546da0944632b853313aa52f38cc00.zip opensim-SC-3c9f8c9c46546da0944632b853313aa52f38cc00.tar.gz opensim-SC-3c9f8c9c46546da0944632b853313aa52f38cc00.tar.bz2 opensim-SC-3c9f8c9c46546da0944632b853313aa52f38cc00.tar.xz |
Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
Diffstat (limited to 'OpenSim')
27 files changed, 1133 insertions, 416 deletions
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs index 04cc33a..b497fde 100644 --- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs +++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs | |||
@@ -246,6 +246,11 @@ namespace OpenSim.Capabilities.Handlers | |||
246 | } | 246 | } |
247 | else | 247 | else |
248 | { | 248 | { |
249 | // Handle the case where no second range value was given. This is equivalent to requesting | ||
250 | // the rest of the entity. | ||
251 | if (end == -1) | ||
252 | end = int.MaxValue; | ||
253 | |||
249 | end = Utils.Clamp(end, 0, texture.Data.Length - 1); | 254 | end = Utils.Clamp(end, 0, texture.Data.Length - 1); |
250 | start = Utils.Clamp(start, 0, end); | 255 | start = Utils.Clamp(start, 0, end); |
251 | int len = end - start + 1; | 256 | int len = end - start + 1; |
@@ -299,15 +304,43 @@ namespace OpenSim.Capabilities.Handlers | |||
299 | // texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length); | 304 | // texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length); |
300 | } | 305 | } |
301 | 306 | ||
307 | /// <summary> | ||
308 | /// Parse a range header. | ||
309 | /// </summary> | ||
310 | /// <remarks> | ||
311 | /// As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, | ||
312 | /// this obeys range headers with two values (e.g. 533-4165) and no second value (e.g. 533-). | ||
313 | /// Where there is no value, -1 is returned. | ||
314 | /// FIXME: Need to cover the case where only a second value is specified (e.g. -4165), probably by returning -1 | ||
315 | /// for start.</remarks> | ||
316 | /// <returns></returns> | ||
317 | /// <param name='header'></param> | ||
318 | /// <param name='start'>Start of the range. Undefined if this was not a number.</param> | ||
319 | /// <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> | ||
302 | private bool TryParseRange(string header, out int start, out int end) | 320 | private bool TryParseRange(string header, out int start, out int end) |
303 | { | 321 | { |
322 | start = end = 0; | ||
323 | |||
304 | if (header.StartsWith("bytes=")) | 324 | if (header.StartsWith("bytes=")) |
305 | { | 325 | { |
306 | string[] rangeValues = header.Substring(6).Split('-'); | 326 | string[] rangeValues = header.Substring(6).Split('-'); |
327 | |||
307 | if (rangeValues.Length == 2) | 328 | if (rangeValues.Length == 2) |
308 | { | 329 | { |
309 | if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end)) | 330 | if (!Int32.TryParse(rangeValues[0], out start)) |
331 | return false; | ||
332 | |||
333 | string rawEnd = rangeValues[1]; | ||
334 | |||
335 | if (rawEnd == "") | ||
336 | { | ||
337 | end = -1; | ||
338 | return true; | ||
339 | } | ||
340 | else if (Int32.TryParse(rawEnd, out end)) | ||
341 | { | ||
310 | return true; | 342 | return true; |
343 | } | ||
311 | } | 344 | } |
312 | } | 345 | } |
313 | 346 | ||
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 | |||
27 | using System; | ||
28 | using System.Threading; | ||
29 | using System.Collections.Generic; | ||
30 | |||
31 | namespace 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 76dcfca..4c36819 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 2cd626f..8a0340f 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | |||
@@ -436,7 +436,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
436 | // reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]); | 436 | // reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]); |
437 | //m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl); | 437 | //m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl); |
438 | 438 | ||
439 | Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); | 439 | Culture.SetCurrentCulture(); |
440 | 440 | ||
441 | // // This is the REST agent interface. We require an agent to properly identify | 441 | // // This is the REST agent interface. We require an agent to properly identify |
442 | // // itself. If the REST handler recognizes the prefix it will attempt to | 442 | // // 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 47fe599..1dc8053 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 3983369..fa935cd 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs | |||
@@ -146,7 +146,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage | |||
146 | if (sp != null && !sp.IsChildAgent) | 146 | if (sp != null && !sp.IsChildAgent) |
147 | { | 147 | { |
148 | // Local message | 148 | // Local message |
149 | m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); | 149 | // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); |
150 | 150 | ||
151 | sp.ControllingClient.SendInstantMessage(im); | 151 | sp.ControllingClient.SendInstantMessage(im); |
152 | 152 | ||
@@ -159,14 +159,14 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage | |||
159 | // try child avatar second | 159 | // try child avatar second |
160 | foreach (Scene scene in m_Scenes) | 160 | foreach (Scene scene in m_Scenes) |
161 | { | 161 | { |
162 | m_log.DebugFormat( | 162 | // m_log.DebugFormat( |
163 | "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); | 163 | // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); |
164 | 164 | ||
165 | ScenePresence sp = scene.GetScenePresence(toAgentID); | 165 | ScenePresence sp = scene.GetScenePresence(toAgentID); |
166 | if (sp != null) | 166 | if (sp != null) |
167 | { | 167 | { |
168 | // Local message | 168 | // Local message |
169 | m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID); | 169 | // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID); |
170 | 170 | ||
171 | sp.ControllingClient.SendInstantMessage(im); | 171 | sp.ControllingClient.SendInstantMessage(im); |
172 | 172 | ||
@@ -176,7 +176,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage | |||
176 | } | 176 | } |
177 | } | 177 | } |
178 | 178 | ||
179 | m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); | 179 | // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); |
180 | 180 | ||
181 | SendGridInstantMessageViaXMLRPC(im, result); | 181 | SendGridInstantMessageViaXMLRPC(im, result); |
182 | } | 182 | } |
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; | |||
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using log4net; | 32 | using log4net; |
33 | using OpenMetaverse; | 33 | using OpenMetaverse; |
34 | using OpenSim.Framework; | ||
34 | 35 | ||
35 | namespace OpenSim.Region.Framework.Scenes | 36 | namespace 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 1ad5edd..cca295c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -5638,10 +5638,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
5638 | return m_SpawnPoint - 1; | 5638 | return m_SpawnPoint - 1; |
5639 | } | 5639 | } |
5640 | 5640 | ||
5641 | // Wrappers to get physics modules retrieve assets. Has to be done this way | 5641 | /// <summary> |
5642 | // because we can't assign the asset service to physics directly - at the | 5642 | /// Wrappers to get physics modules retrieve assets. |
5643 | // time physics are instantiated it's not registered but it will be by | 5643 | /// </summary> |
5644 | // the time the first prim exists. | 5644 | /// <remarks> |
5645 | /// Has to be done this way | ||
5646 | /// because we can't assign the asset service to physics directly - at the | ||
5647 | /// time physics are instantiated it's not registered but it will be by | ||
5648 | /// the time the first prim exists. | ||
5649 | /// </remarks> | ||
5650 | /// <param name="assetID"></param> | ||
5651 | /// <param name="callback"></param> | ||
5645 | public void PhysicsRequestAsset(UUID assetID, AssetReceivedDelegate callback) | 5652 | public void PhysicsRequestAsset(UUID assetID, AssetReceivedDelegate callback) |
5646 | { | 5653 | { |
5647 | AssetService.Get(assetID.ToString(), callback, PhysicsAssetReceived); | 5654 | 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 | ||
44 | using System; | 33 | using 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 | */ |
27 | using System; | 27 | using System; |
28 | using System.Collections.Generic; | 28 | using System.Collections.Generic; |
29 | using System.Text; | 29 | using System.Text; |
30 | using System.Reflection; | 30 | using System.Reflection; |
31 | using Nini.Config; | 31 | using Nini.Config; |
32 | 32 | ||
33 | namespace OpenSim.Region.Physics.BulletSPlugin | 33 | namespace OpenSim.Region.Physics.BulletSPlugin |
34 | { | 34 | { |
35 | 35 | ||
36 | public struct MaterialAttributes | 36 | public 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; | 71 | public static class BSMaterials |
72 | public float ccdMotionThreshold; | 72 | { |
73 | public float ccdSweptSphereRadius; | 73 | public static MaterialAttributes[] Attributes; |
74 | } | 74 | |
75 | 75 | static BSMaterials() | |
76 | public 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 b94dcf6..e77b6ba 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 | ||
9 | BULLETSIM TODO LIST: | 9 | VEHICLES TODO LIST: |
10 | ================================================= | 10 | ================================================= |
11 | Neb car jiggling left and right | 11 | Neb car jiggling left and right |
12 | Happens on terrain and any other mesh object. Flat cubes are much smoother. | ||
12 | Vehicles (Move smoothly) | 13 | Vehicles (Move smoothly) |
13 | Light cycle falling over when driving | 14 | Add vehicle collisions so IsColliding is properly reported. |
14 | Light cycle not banking | 15 | Needed for banking, limitMotorUp, movementLimiting, ... |
15 | Do single prim vehicles don't seem to properly vehiclize. | 16 | Some vehicles should not be able to turn if no speed or off ground. |
16 | Gun sending shooter flying | 17 | For limitMotorUp, use raycast down to find if vehicle is in the air. |
18 | Implement function efficiency for lineaar and angular motion. | ||
19 | Should vehicle angular/linear movement friction happen after all the components | ||
20 | or does it only apply to the basic movement? | ||
21 | After 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 | ||
23 | Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint) | ||
24 | Implement referenceFrame for all the motion routines. | ||
25 | Cannot edit/move a vehicle being ridden: it jumps back to the origional position. | ||
26 | |||
27 | BULLETSIM TODO LIST: | ||
28 | ================================================= | ||
29 | Disable 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, ... | ||
32 | Scenes with hundred of thousands of static objects take a lot of physics CPU time. | ||
33 | BSPrim.Force should set a continious force on the prim. The force should be | ||
34 | applied each tick. Some limits? | ||
35 | Single prim vehicles don't seem to properly vehiclize. | ||
36 | Gun sending shooter flying. | ||
17 | Collision margin (gap between physical objects lying on each other) | 37 | Collision margin (gap between physical objects lying on each other) |
18 | Boundry checking (crashes related to crossing boundry) | 38 | Boundry 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 | |||
28 | Add material type linkage and input all the material property definitions. | 48 | Add 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. |
30 | Add PID motor for avatar movement (slow to stop, ...) | 50 | Add PID motor for avatar movement (slow to stop, ...) |
31 | Implement function efficiency for lineaar and angular motion. | 51 | setForce should set a constant force. Different than AddImpulse. |
52 | Implement raycast. | ||
53 | Implement ShapeCollection.Dispose() | ||
54 | Implement water as a plain so raycasting and collisions can happen with same. | ||
32 | 55 | ||
33 | After 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 | ||
35 | Find/remove avatar collision with ID=0. | 56 | Find/remove avatar collision with ID=0. |
36 | Test avatar walking up stairs. How does compare with SL. | 57 | Test 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. | |||
39 | Debounce avatar contact so legs don't keep folding up when standing. | 60 | Debounce avatar contact so legs don't keep folding up when standing. |
40 | Implement LSL physics controls. Like STATUS_ROTATE_X. | 61 | Implement LSL physics controls. Like STATUS_ROTATE_X. |
41 | Add border extensions to terrain to help region crossings and objects leaving region. | 62 | Add border extensions to terrain to help region crossings and objects leaving region. |
42 | Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint) | ||
43 | 63 | ||
44 | Speed up creation of large physical linksets | 64 | Speed 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 |
46 | Performance test with lots of avatars. Can BulletSim support a thousand? | 66 | Performance test with lots of avatars. Can BulletSim support a thousand? |
47 | Optimize collisions in C++: only send up to the object subscribed to collisions. | 67 | Optimize 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) |
49 | Check wheter SimMotionState needs large if statement (see TODO). | 69 | Check whether SimMotionState needs large if statement (see TODO). |
50 | 70 | ||
51 | Implement 'top colliders' info. | 71 | Implement 'top colliders' info. |
52 | Avatar jump | 72 | Avatar jump |
53 | Implement meshes or just verify that they work. | ||
54 | Do prim hash codes work for sculpties and meshes? | ||
55 | Performance measurement and changes to make quicker. | 73 | Performance measurement and changes to make quicker. |
56 | Implement detailed physics stats (GetStats()). | 74 | Implement detailed physics stats (GetStats()). |
57 | 75 | ||
@@ -67,8 +85,6 @@ Performance of closures and delegates for taint processing | |||
67 | Is there are more efficient method of implementing pre and post step actions? | 85 | Is 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 | ||
70 | Package Bullet source mods for Bullet internal stats output | ||
71 | |||
72 | Physics Arena central pyramid: why is one side permiable? | 88 | Physics Arena central pyramid: why is one side permiable? |
73 | 89 | ||
74 | INTERNAL IMPROVEMENT/CLEANUP | 90 | INTERNAL 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? |
87 | Implement linkset by setting position of children when root updated. (LinksetManual) | 103 | Implement linkset by setting position of children when root updated. (LinksetManual) |
104 | Linkset implementation using manual prim movement. | ||
88 | LinkablePrim class? Would that simplify/centralize the linkset logic? | 105 | LinkablePrim class? Would that simplify/centralize the linkset logic? |
89 | Linkset implementation using manual prim movement. | ||
90 | Linkset implementation using compound shapes. | ||
91 | Compound shapes will need the LocalID in the shapes and collision | ||
92 | processing to get it from there. | ||
93 | BSScene.UpdateParameterSet() is broken. How to set params on objects? | 106 | BSScene.UpdateParameterSet() is broken. How to set params on objects? |
94 | Remove HeightmapInfo from terrain specification. | 107 | Remove 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. |
96 | Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will | 109 | Add 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 | ||
112 | THREADING | ||
113 | ================================================= | ||
114 | Do 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 | |||
99 | DONE DONE DONE DONE | 117 | DONE DONE DONE DONE |
100 | ================================================= | 118 | ================================================= |
101 | Cleanup code in BSDynamics by using motors. | 119 | Cleanup code in BSDynamics by using motors. (Resolution: started) |
102 | Consider implementing terrain with a mesh rather than heightmap. | 120 | Consider implementing terrain with a mesh rather than heightmap. (Resolution: done) |
103 | Would have better and adjustable resolution. | 121 | Would have better and adjustable resolution. |
104 | NOTDONE: Build terrain mesh so heighmap is height of the center of the square meter. | 122 | Build 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. |
106 | Terrain as mesh. | 124 | Terrain as mesh. (Resolution: done) |
107 | How are static linksets seen by the physics engine? | 125 | How 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. |
109 | Remember to remove BSScene.DetailLog Refresh call. | 127 | Convert BSCharacter to use all API2 (Resolution: done) |
110 | Convert BSCharacter to use all API2 | ||
111 | Avatar pushing difficult (too heavy?) | 128 | Avatar pushing difficult (too heavy?) |
112 | Use asset service passed to BulletSim to get sculptie bodies, etc. | 129 | Use asset service passed to BulletSim to get sculptie bodies, etc. (Resolution: done) |
113 | Vehicles (fix bouncing on terrain) | 130 | Remove old code in DLL (all non-API2 stuff). (Resolution: done) |
114 | Remove old code in DLL (all non-API2 stuff). | 131 | Measurements of mega-physical prim performance (with graph) (Resolution: done, email) |
115 | Measurements of mega-physical prim performance (with graph) | ||
116 | Debug Bullet internal stats output (why is timing all wrong?) | 132 | Debug 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). |
134 | Implement meshes or just verify that they work. (Resolution: they do!) | ||
135 | Do prim hash codes work for sculpties and meshes? (Resolution: yes) | ||
136 | Linkset 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. | ||
139 | Light cycle falling over when driving (Resolution: implemented VerticalAttractor) | ||
140 | Light cycle not banking (Resolution: It doesn't. Banking is roll adding yaw.) | ||
141 | Package 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 5793cc9..5ad6eeb 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | |||
@@ -173,6 +173,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
173 | 173 | ||
174 | public Queue EventQueue { get; private set; } | 174 | public Queue EventQueue { get; private set; } |
175 | 175 | ||
176 | public long EventsQueued | ||
177 | { | ||
178 | get | ||
179 | { | ||
180 | lock (EventQueue) | ||
181 | return EventQueue.Count; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | public long EventsProcessed { get; private set; } | ||
186 | |||
176 | public int StartParam { get; set; } | 187 | public int StartParam { get; set; } |
177 | 188 | ||
178 | public TaskInventoryItem ScriptTask { get; private set; } | 189 | public TaskInventoryItem ScriptTask { get; private set; } |
@@ -774,6 +785,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
774 | ChatTypeEnum.DebugChannel, 2147483647, | 785 | ChatTypeEnum.DebugChannel, 2147483647, |
775 | part.AbsolutePosition, | 786 | part.AbsolutePosition, |
776 | part.Name, part.UUID, false); | 787 | part.Name, part.UUID, false); |
788 | |||
789 | |||
790 | m_log.DebugFormat( | ||
791 | "[SCRIPT INSTANCE]: Runtime error in script {0}, part {1} {2} at {3} in {4}, displayed error {5}, actual exception {6}", | ||
792 | ScriptName, | ||
793 | PrimName, | ||
794 | part.UUID, | ||
795 | part.AbsolutePosition, | ||
796 | part.ParentGroup.Scene.Name, | ||
797 | text.Replace("\n", "\\n"), | ||
798 | e.InnerException); | ||
777 | } | 799 | } |
778 | catch (Exception) | 800 | catch (Exception) |
779 | { | 801 | { |
@@ -808,6 +830,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
808 | // script engine to run the next event. | 830 | // script engine to run the next event. |
809 | lock (EventQueue) | 831 | lock (EventQueue) |
810 | { | 832 | { |
833 | EventsProcessed++; | ||
834 | |||
811 | if (EventQueue.Count > 0 && Running && !ShuttingDown) | 835 | if (EventQueue.Count > 0 && Running && !ShuttingDown) |
812 | { | 836 | { |
813 | m_CurrentWorkItem = Engine.QueueEventHandler(this); | 837 | m_CurrentWorkItem = Engine.QueueEventHandler(this); |
@@ -1013,7 +1037,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
1013 | "({0}): {1}", scriptLine - 1, | 1037 | "({0}): {1}", scriptLine - 1, |
1014 | e.InnerException.Message); | 1038 | e.InnerException.Message); |
1015 | 1039 | ||
1016 | System.Console.WriteLine(e.ToString()+"\n"); | ||
1017 | return message; | 1040 | return message; |
1018 | } | 1041 | } |
1019 | } | 1042 | } |
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 0460f22..965101a 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | |||
@@ -30,6 +30,7 @@ using System.Collections; | |||
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Globalization; | 31 | using System.Globalization; |
32 | using System.IO; | 32 | using System.IO; |
33 | using System.Linq; | ||
33 | using System.Reflection; | 34 | using System.Reflection; |
34 | using System.Security; | 35 | using System.Security; |
35 | using System.Security.Policy; | 36 | using System.Security.Policy; |
@@ -377,9 +378,21 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
377 | /// </summary> | 378 | /// </summary> |
378 | /// <param name="cmdparams"></param> | 379 | /// <param name="cmdparams"></param> |
379 | /// <param name="instance"></param> | 380 | /// <param name="instance"></param> |
380 | /// <returns>true if we're okay to proceed, false if not.</returns> | 381 | /// <param name="comparer">Basis on which to sort output. Can be null if no sort needs to take place</param> |
381 | private void HandleScriptsAction(string[] cmdparams, Action<IScriptInstance> action) | 382 | private void HandleScriptsAction(string[] cmdparams, Action<IScriptInstance> action) |
382 | { | 383 | { |
384 | HandleScriptsAction<object>(cmdparams, action, null); | ||
385 | } | ||
386 | |||
387 | /// <summary> | ||
388 | /// Parse the raw item id into a script instance from the command params if it's present. | ||
389 | /// </summary> | ||
390 | /// <param name="cmdparams"></param> | ||
391 | /// <param name="instance"></param> | ||
392 | /// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param> | ||
393 | private void HandleScriptsAction<TKey>( | ||
394 | string[] cmdparams, Action<IScriptInstance> action, Func<IScriptInstance, TKey> keySelector) | ||
395 | { | ||
383 | if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) | 396 | if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) |
384 | return; | 397 | return; |
385 | 398 | ||
@@ -390,7 +403,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
390 | 403 | ||
391 | if (cmdparams.Length == 2) | 404 | if (cmdparams.Length == 2) |
392 | { | 405 | { |
393 | foreach (IScriptInstance instance in m_Scripts.Values) | 406 | IEnumerable<IScriptInstance> scripts = m_Scripts.Values; |
407 | |||
408 | if (keySelector != null) | ||
409 | scripts = scripts.OrderBy<IScriptInstance, TKey>(keySelector); | ||
410 | |||
411 | foreach (IScriptInstance instance in scripts) | ||
394 | action(instance); | 412 | action(instance); |
395 | 413 | ||
396 | return; | 414 | return; |
@@ -437,9 +455,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
437 | StringBuilder sb = new StringBuilder(); | 455 | StringBuilder sb = new StringBuilder(); |
438 | sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName); | 456 | sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName); |
439 | 457 | ||
458 | long scriptsLoaded, eventsQueued = 0, eventsProcessed = 0; | ||
459 | |||
440 | lock (m_Scripts) | 460 | lock (m_Scripts) |
441 | sb.AppendFormat("Scripts loaded : {0}\n", m_Scripts.Count); | 461 | { |
462 | scriptsLoaded = m_Scripts.Count; | ||
442 | 463 | ||
464 | foreach (IScriptInstance si in m_Scripts.Values) | ||
465 | { | ||
466 | eventsQueued += si.EventsQueued; | ||
467 | eventsProcessed += si.EventsProcessed; | ||
468 | } | ||
469 | } | ||
470 | |||
471 | sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded); | ||
443 | sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count); | 472 | sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count); |
444 | sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); | 473 | sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); |
445 | sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads); | 474 | sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads); |
@@ -448,6 +477,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
448 | sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads); | 477 | sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads); |
449 | sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks); | 478 | sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks); |
450 | // sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count); | 479 | // sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count); |
480 | sb.AppendFormat("Events queued : {0}\n", eventsQueued); | ||
481 | sb.AppendFormat("Events processed : {0}\n", eventsProcessed); | ||
451 | 482 | ||
452 | SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this); | 483 | SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this); |
453 | sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0); | 484 | sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0); |
@@ -478,7 +509,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
478 | } | 509 | } |
479 | } | 510 | } |
480 | 511 | ||
481 | HandleScriptsAction(cmdparams, HandleShowScript); | 512 | HandleScriptsAction<long>(cmdparams, HandleShowScript, si => si.EventsProcessed); |
482 | } | 513 | } |
483 | 514 | ||
484 | private void HandleShowScript(IScriptInstance instance) | 515 | private void HandleShowScript(IScriptInstance instance) |
@@ -508,10 +539,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
508 | 539 | ||
509 | sb.AppendFormat("Script name : {0}\n", instance.ScriptName); | 540 | sb.AppendFormat("Script name : {0}\n", instance.ScriptName); |
510 | sb.AppendFormat("Status : {0}\n", status); | 541 | sb.AppendFormat("Status : {0}\n", status); |
511 | 542 | sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued); | |
512 | lock (eq) | 543 | sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed); |
513 | sb.AppendFormat("Queued events : {0}\n", eq.Count); | ||
514 | |||
515 | sb.AppendFormat("Item UUID : {0}\n", instance.ItemID); | 544 | sb.AppendFormat("Item UUID : {0}\n", instance.ItemID); |
516 | sb.AppendFormat("Containing part name: {0}\n", instance.PrimName); | 545 | sb.AppendFormat("Containing part name: {0}\n", instance.PrimName); |
517 | sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID); | 546 | sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID); |
@@ -1018,8 +1047,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1018 | 1047 | ||
1019 | string assembly = ""; | 1048 | string assembly = ""; |
1020 | 1049 | ||
1021 | CultureInfo USCulture = new CultureInfo("en-US"); | 1050 | Culture.SetCurrentCulture(); |
1022 | Thread.CurrentThread.CurrentCulture = USCulture; | ||
1023 | 1051 | ||
1024 | Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap; | 1052 | Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap; |
1025 | 1053 | ||
@@ -1415,8 +1443,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1415 | /// <returns></returns> | 1443 | /// <returns></returns> |
1416 | private object ProcessEventHandler(object parms) | 1444 | private object ProcessEventHandler(object parms) |
1417 | { | 1445 | { |
1418 | CultureInfo USCulture = new CultureInfo("en-US"); | 1446 | Culture.SetCurrentCulture(); |
1419 | Thread.CurrentThread.CurrentCulture = USCulture; | ||
1420 | 1447 | ||
1421 | IScriptInstance instance = (ScriptInstance) parms; | 1448 | IScriptInstance instance = (ScriptInstance) parms; |
1422 | 1449 | ||