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