aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs58
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs12
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs285
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs174
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs109
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs158
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs137
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs138
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActors.cs59
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs271
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs30
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs53
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs233
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs329
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs9
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs1
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs223
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs6
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt3
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs83
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs7
23 files changed, 1501 insertions, 880 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 5aad7f0..bbe7446 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -358,7 +358,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
358 bool asAttachment) 358 bool asAttachment)
359 { 359 {
360 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); 360 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
361 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); 361// Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
362 362
363 foreach (SceneObjectGroup objectGroup in objlist) 363 foreach (SceneObjectGroup objectGroup in objlist)
364 { 364 {
@@ -379,7 +379,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
379 objectGroup.AbsolutePosition.Z); 379 objectGroup.AbsolutePosition.Z);
380 380
381 Quaternion inventoryStoredRotation = objectGroup.GroupRotation; 381 Quaternion inventoryStoredRotation = objectGroup.GroupRotation;
382 originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; 382 //originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition;
383 383
384 // Restore attachment data after trip through the sim 384 // Restore attachment data after trip through the sim
385 if (objectGroup.RootPart.AttachPoint > 0) 385 if (objectGroup.RootPart.AttachPoint > 0)
@@ -418,9 +418,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
418 else 418 else
419 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment); 419 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment);
420 420
421 // Restore the position of each group now that it has been stored to inventory. 421// // Restore the position of each group now that it has been stored to inventory.
422 foreach (SceneObjectGroup objectGroup in objlist) 422// foreach (SceneObjectGroup objectGroup in objlist)
423 objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; 423// objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
424 424
425 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); 425 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
426 426
@@ -866,7 +866,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
866 return null; 866 return null;
867 } 867 }
868 868
869 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, attachment)) 869 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment))
870 return null; 870 return null;
871 871
872 for (int i = 0; i < objlist.Count; i++) 872 for (int i = 0; i < objlist.Count; i++)
@@ -965,10 +965,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
965 /// <param name="item"></param> 965 /// <param name="item"></param>
966 /// <param name="objlist"></param> 966 /// <param name="objlist"></param>
967 /// <param name="pos"></param> 967 /// <param name="pos"></param>
968 /// <param name="veclist">
969 /// List of vector position adjustments for a coalesced objects. For ordinary objects
970 /// this list will contain just Vector3.Zero. The order of adjustments must match the order of objlist
971 /// </param>
968 /// <param name="isAttachment"></param> 972 /// <param name="isAttachment"></param>
969 /// <returns>true if we can processed with rezzing, false if we need to abort</returns> 973 /// <returns>true if we can processed with rezzing, false if we need to abort</returns>
970 private bool DoPreRezWhenFromItem( 974 private bool DoPreRezWhenFromItem(
971 IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist, Vector3 pos, bool isAttachment) 975 IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist,
976 Vector3 pos, List<Vector3> veclist, bool isAttachment)
972 { 977 {
973 UUID fromUserInventoryItemId = UUID.Zero; 978 UUID fromUserInventoryItemId = UUID.Zero;
974 979
@@ -991,28 +996,29 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
991 } 996 }
992 } 997 }
993 998
994 int primcount = 0; 999 for (int i = 0; i < objlist.Count; i++)
995 foreach (SceneObjectGroup g in objlist)
996 primcount += g.PrimCount;
997
998 if (!m_Scene.Permissions.CanRezObject(
999 primcount, remoteClient.AgentId, pos)
1000 && !isAttachment)
1001 { 1000 {
1002 // The client operates in no fail mode. It will 1001 SceneObjectGroup g = objlist[i];
1003 // have already removed the item from the folder 1002
1004 // if it's no copy. 1003 if (!m_Scene.Permissions.CanRezObject(
1005 // Put it back if it's not an attachment 1004 g.PrimCount, remoteClient.AgentId, pos + veclist[i])
1006 // 1005 && !isAttachment)
1007 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment)) 1006 {
1008 remoteClient.SendBulkUpdateInventory(item); 1007 // The client operates in no fail mode. It will
1008 // have already removed the item from the folder
1009 // if it's no copy.
1010 // Put it back if it's not an attachment
1011 //
1012 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment))
1013 remoteClient.SendBulkUpdateInventory(item);
1009 1014
1010 ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); 1015 ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y);
1011 remoteClient.SendAlertMessage(string.Format( 1016 remoteClient.SendAlertMessage(string.Format(
1012 "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.", 1017 "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.",
1013 item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.RegionInfo.RegionName)); 1018 item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.Name));
1014 1019
1015 return false; 1020 return false;
1021 }
1016 } 1022 }
1017 1023
1018 for (int i = 0; i < objlist.Count; i++) 1024 for (int i = 0; i < objlist.Count; i++)
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index 2b13a8b..de8539f 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -412,7 +412,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
412 //public bool HttpVerboseThrottle = true; // not implemented 412 //public bool HttpVerboseThrottle = true; // not implemented
413 public List<string> HttpCustomHeaders = null; 413 public List<string> HttpCustomHeaders = null;
414 public bool HttpPragmaNoCache = true; 414 public bool HttpPragmaNoCache = true;
415 private Thread httpThread;
416 415
417 // Request info 416 // Request info
418 private UUID _itemID; 417 private UUID _itemID;
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 79dd4a0..f8e93e1 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -1453,6 +1453,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1453 1453
1454 bool permission = false; 1454 bool permission = false;
1455 1455
1456// m_log.DebugFormat("[PERMISSIONS MODULE]: Checking rez object at {0} in {1}", objectPosition, m_scene.Name);
1457
1456 ILandObject land = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); 1458 ILandObject land = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y);
1457 if (land == null) return false; 1459 if (land == null) return false;
1458 1460
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 28fce53..a2510a78 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -5647,12 +5647,12 @@ Environment.Exit(1);
5647 List<SceneObjectGroup> objects, 5647 List<SceneObjectGroup> objects,
5648 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 5648 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
5649 { 5649 {
5650 minX = 256; 5650 minX = float.MaxValue;
5651 maxX = -256; 5651 maxX = float.MinValue;
5652 minY = 256; 5652 minY = float.MaxValue;
5653 maxY = -256; 5653 maxY = float.MinValue;
5654 minZ = 8192; 5654 minZ = float.MaxValue;
5655 maxZ = -256; 5655 maxZ = float.MinValue;
5656 5656
5657 List<Vector3> offsets = new List<Vector3>(); 5657 List<Vector3> offsets = new List<Vector3>();
5658 5658
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
new file mode 100755
index 0000000..8416740
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
@@ -0,0 +1,285 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
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 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
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
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
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenSim.Region.Physics.Manager;
34
35using OMV = OpenMetaverse;
36
37namespace OpenSim.Region.Physics.BulletSPlugin
38{
39public class BSActorAvatarMove : BSActor
40{
41 BSVMotor m_velocityMotor;
42
43 public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
44 : base(physicsScene, pObj, actorName)
45 {
46 m_velocityMotor = null;
47 m_physicsScene.DetailLog("{0},BSActorAvatarMove,constructor", m_controllingPrim.LocalID);
48 }
49
50 // BSActor.isActive
51 public override bool isActive
52 {
53 get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
54 }
55
56 // Release any connections and resources used by the actor.
57 // BSActor.Dispose()
58 public override void Dispose()
59 {
60 Enabled = false;
61 }
62
63 // Called when physical parameters (properties set in Bullet) need to be re-applied.
64 // Called at taint-time.
65 // BSActor.Refresh()
66 public override void Refresh()
67 {
68 m_physicsScene.DetailLog("{0},BSActorAvatarMove,refresh", m_controllingPrim.LocalID);
69
70 // If the object is physically active, add the hoverer prestep action
71 if (isActive)
72 {
73 ActivateAvatarMove();
74 }
75 else
76 {
77 DeactivateAvatarMove();
78 }
79 }
80
81 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
82 // Register a prestep action to restore physical requirements before the next simulation step.
83 // Called at taint-time.
84 // BSActor.RemoveBodyDependencies()
85 public override void RemoveBodyDependencies()
86 {
87 // Nothing to do for the hoverer since it is all software at pre-step action time.
88 }
89
90 // Usually called when target velocity changes to set the current velocity and the target
91 // into the movement motor.
92 public void SetVelocityAndTarget(OMV.Vector3 vel, OMV.Vector3 targ, bool inTaintTime)
93 {
94 m_physicsScene.TaintedObject(inTaintTime, "BSActorAvatarMove.setVelocityAndTarget", delegate()
95 {
96 if (m_velocityMotor != null)
97 {
98 m_velocityMotor.Reset();
99 m_velocityMotor.SetTarget(targ);
100 m_velocityMotor.SetCurrent(vel);
101 m_velocityMotor.Enabled = true;
102 }
103 });
104 }
105
106 // If a hover motor has not been created, create one and start the hovering.
107 private void ActivateAvatarMove()
108 {
109 if (m_velocityMotor == null)
110 {
111 // Infinite decay and timescale values so motor only changes current to target values.
112 m_velocityMotor = new BSVMotor("BSCharacter.Velocity",
113 0.2f, // time scale
114 BSMotor.Infinite, // decay time scale
115 BSMotor.InfiniteVector, // friction timescale
116 1f // efficiency
117 );
118 // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
119 SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */);
120
121 m_physicsScene.BeforeStep += Mover;
122 }
123 }
124
125 private void DeactivateAvatarMove()
126 {
127 if (m_velocityMotor != null)
128 {
129 m_physicsScene.BeforeStep -= Mover;
130 m_velocityMotor = null;
131 }
132 }
133
134 // Called just before the simulation step. Update the vertical position for hoverness.
135 private void Mover(float timeStep)
136 {
137 // Don't do movement while the object is selected.
138 if (!isActive)
139 return;
140
141 // TODO: Decide if the step parameters should be changed depending on the avatar's
142 // state (flying, colliding, ...). There is code in ODE to do this.
143
144 // COMMENTARY: when the user is making the avatar walk, except for falling, the velocity
145 // specified for the avatar is the one that should be used. For falling, if the avatar
146 // is not flying and is not colliding then it is presumed to be falling and the Z
147 // component is not fooled with (thus allowing gravity to do its thing).
148 // When the avatar is standing, though, the user has specified a velocity of zero and
149 // the avatar should be standing. But if the avatar is pushed by something in the world
150 // (raising elevator platform, moving vehicle, ...) the avatar should be allowed to
151 // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity
152 // errors can creap in and the avatar will slowly float off in some direction.
153 // So, the problem is that, when an avatar is standing, we cannot tell creaping error
154 // from real pushing.
155 // The code below uses whether the collider is static or moving to decide whether to zero motion.
156
157 m_velocityMotor.Step(timeStep);
158 m_controllingPrim.IsStationary = false;
159
160 // If we're not supposed to be moving, make sure things are zero.
161 if (m_velocityMotor.ErrorIsZero() && m_velocityMotor.TargetValue == OMV.Vector3.Zero)
162 {
163 // The avatar shouldn't be moving
164 m_velocityMotor.Zero();
165
166 if (m_controllingPrim.IsColliding)
167 {
168 // If we are colliding with a stationary object, presume we're standing and don't move around
169 if (!m_controllingPrim.ColliderIsMoving)
170 {
171 m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID);
172 m_controllingPrim.IsStationary = true;
173 m_controllingPrim.ZeroMotion(true /* inTaintTime */);
174 }
175
176 // Standing has more friction on the ground
177 if (m_controllingPrim.Friction != BSParam.AvatarStandingFriction)
178 {
179 m_controllingPrim.Friction = BSParam.AvatarStandingFriction;
180 m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
181 }
182 }
183 else
184 {
185 if (m_controllingPrim.Flying)
186 {
187 // Flying and not collising and velocity nearly zero.
188 m_controllingPrim.ZeroMotion(true /* inTaintTime */);
189 }
190 }
191
192 m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}",
193 m_controllingPrim.LocalID, m_velocityMotor.TargetValue, m_controllingPrim.IsColliding);
194 }
195 else
196 {
197 // Supposed to be moving.
198 OMV.Vector3 stepVelocity = m_velocityMotor.CurrentValue;
199
200 if (m_controllingPrim.Friction != BSParam.AvatarFriction)
201 {
202 // Probably starting up walking. Set friction to moving friction.
203 m_controllingPrim.Friction = BSParam.AvatarFriction;
204 m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
205 }
206
207 // If falling, we keep the world's downward vector no matter what the other axis specify.
208 // The check for RawVelocity.Z < 0 makes jumping work (temporary upward force).
209 if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding)
210 {
211 if (m_controllingPrim.RawVelocity.Z < 0)
212 stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
213 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
214 }
215
216 // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
217 OMV.Vector3 moveForce = (stepVelocity - m_controllingPrim.RawVelocity) * m_controllingPrim.Mass;
218
219 // Should we check for move force being small and forcing velocity to zero?
220
221 // Add special movement force to allow avatars to walk up stepped surfaces.
222 moveForce += WalkUpStairs();
223
224 m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}",
225 m_controllingPrim.LocalID, stepVelocity, m_controllingPrim.RawVelocity, m_controllingPrim.Mass, moveForce);
226 m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, moveForce);
227 }
228 }
229
230 // Decide if the character is colliding with a low object and compute a force to pop the
231 // avatar up so it can walk up and over the low objects.
232 private OMV.Vector3 WalkUpStairs()
233 {
234 OMV.Vector3 ret = OMV.Vector3.Zero;
235
236 // This test is done if moving forward, not flying and is colliding with something.
237 // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
238 // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
239 if (m_controllingPrim.IsColliding && !m_controllingPrim.Flying && m_controllingPrim.TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */)
240 {
241 // The range near the character's feet where we will consider stairs
242 float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) + 0.05f;
243 float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
244
245 // Look for a collision point that is near the character's feet and is oriented the same as the charactor is
246 foreach (KeyValuePair<uint, ContactPoint> kvp in m_controllingPrim.CollisionsLastTick.m_objCollisionList)
247 {
248 // Don't care about collisions with the terrain
249 if (kvp.Key > m_physicsScene.TerrainManager.HighestTerrainID)
250 {
251 OMV.Vector3 touchPosition = kvp.Value.Position;
252 // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
253 // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
254 if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
255 {
256 // This contact is within the 'near the feet' range.
257 // The normal should be our contact point to the object so it is pointing away
258 // thus the difference between our facing orientation and the normal should be small.
259 OMV.Vector3 directionFacing = OMV.Vector3.UnitX * m_controllingPrim.RawOrientation;
260 OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal);
261 float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
262 if (diff < BSParam.AvatarStepApproachFactor)
263 {
264 // Found the stairs contact point. Push up a little to raise the character.
265 float upForce = (touchPosition.Z - nearFeetHeightMin) * m_controllingPrim.Mass * BSParam.AvatarStepForceFactor;
266 ret = new OMV.Vector3(0f, 0f, upForce);
267
268 // Also move the avatar up for the new height
269 OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f);
270 m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement;
271 }
272 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}",
273 m_controllingPrim.LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret);
274 }
275 }
276 }
277 }
278
279 return ret;
280 }
281
282}
283}
284
285
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs
new file mode 100755
index 0000000..92ace66
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs
@@ -0,0 +1,174 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
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 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
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
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
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenSim.Region.Physics.Manager;
34
35using OMV = OpenMetaverse;
36
37namespace OpenSim.Region.Physics.BulletSPlugin
38{
39public class BSActorHover : BSActor
40{
41 private BSFMotor m_hoverMotor;
42
43 public BSActorHover(BSScene physicsScene, BSPhysObject pObj, string actorName)
44 : base(physicsScene, pObj, actorName)
45 {
46 m_hoverMotor = null;
47 m_physicsScene.DetailLog("{0},BSActorHover,constructor", m_controllingPrim.LocalID);
48 }
49
50 // BSActor.isActive
51 public override bool isActive
52 {
53 get { return Enabled; }
54 }
55
56 // Release any connections and resources used by the actor.
57 // BSActor.Dispose()
58 public override void Dispose()
59 {
60 Enabled = false;
61 }
62
63 // Called when physical parameters (properties set in Bullet) need to be re-applied.
64 // Called at taint-time.
65 // BSActor.Refresh()
66 public override void Refresh()
67 {
68 m_physicsScene.DetailLog("{0},BSActorHover,refresh", m_controllingPrim.LocalID);
69
70 // If not active any more, turn me off
71 if (!m_controllingPrim.HoverActive)
72 {
73 SetEnabled(false);
74 }
75
76 // If the object is physically active, add the hoverer prestep action
77 if (isActive)
78 {
79 ActivateHover();
80 }
81 else
82 {
83 DeactivateHover();
84 }
85 }
86
87 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
88 // Register a prestep action to restore physical requirements before the next simulation step.
89 // Called at taint-time.
90 // BSActor.RemoveBodyDependencies()
91 public override void RemoveBodyDependencies()
92 {
93 // Nothing to do for the hoverer since it is all software at pre-step action time.
94 }
95
96 // If a hover motor has not been created, create one and start the hovering.
97 private void ActivateHover()
98 {
99 if (m_hoverMotor == null)
100 {
101 // Turning the target on
102 m_hoverMotor = new BSFMotor("BSActorHover",
103 m_controllingPrim.HoverTau, // timeScale
104 BSMotor.Infinite, // decay time scale
105 BSMotor.Infinite, // friction timescale
106 1f // efficiency
107 );
108 m_hoverMotor.SetTarget(ComputeCurrentHoverHeight());
109 m_hoverMotor.SetCurrent(m_controllingPrim.RawPosition.Z);
110 m_hoverMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages.
111
112 m_physicsScene.BeforeStep += Hoverer;
113 }
114 }
115
116 private void DeactivateHover()
117 {
118 if (m_hoverMotor != null)
119 {
120 m_physicsScene.BeforeStep -= Hoverer;
121 m_hoverMotor = null;
122 }
123 }
124
125 // Called just before the simulation step. Update the vertical position for hoverness.
126 private void Hoverer(float timeStep)
127 {
128 // Don't do hovering while the object is selected.
129 if (!isActive)
130 return;
131
132 m_hoverMotor.SetCurrent(m_controllingPrim.RawPosition.Z);
133 m_hoverMotor.SetTarget(ComputeCurrentHoverHeight());
134 float targetHeight = m_hoverMotor.Step(timeStep);
135
136 // 'targetHeight' is where we'd like the Z of the prim to be at this moment.
137 // Compute the amount of force to push us there.
138 float moveForce = (targetHeight - m_controllingPrim.RawPosition.Z) * m_controllingPrim.RawMass;
139 // Undo anything the object thinks it's doing at the moment
140 moveForce = -m_controllingPrim.RawVelocity.Z * m_controllingPrim.Mass;
141
142 m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, new OMV.Vector3(0f, 0f, moveForce));
143 m_physicsScene.DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}",
144 m_controllingPrim.LocalID, targetHeight, moveForce, m_controllingPrim.RawMass);
145 }
146
147 // Based on current position, determine what we should be hovering at now.
148 // Must recompute often. What if we walked offa cliff>
149 private float ComputeCurrentHoverHeight()
150 {
151 float ret = m_controllingPrim.HoverHeight;
152 float groundHeight = m_physicsScene.TerrainManager.GetTerrainHeightAtXYZ(m_controllingPrim.RawPosition);
153
154 switch (m_controllingPrim.HoverType)
155 {
156 case PIDHoverType.Ground:
157 ret = groundHeight + m_controllingPrim.HoverHeight;
158 break;
159 case PIDHoverType.GroundAndWater:
160 float waterHeight = m_physicsScene.TerrainManager.GetWaterLevelAtXYZ(m_controllingPrim.RawPosition);
161 if (groundHeight > waterHeight)
162 {
163 ret = groundHeight + m_controllingPrim.HoverHeight;
164 }
165 else
166 {
167 ret = waterHeight + m_controllingPrim.HoverHeight;
168 }
169 break;
170 }
171 return ret;
172 }
173}
174}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
index 7219617..09ee32b 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
@@ -36,11 +36,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
36{ 36{
37public class BSActorLockAxis : BSActor 37public class BSActorLockAxis : BSActor
38{ 38{
39 bool TryExperimentalLockAxisCode = true;
40 BSConstraint LockAxisConstraint = null; 39 BSConstraint LockAxisConstraint = null;
41 40
42 public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName) 41 public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName)
43 : base(physicsScene, pObj,actorName) 42 : base(physicsScene, pObj, actorName)
44 { 43 {
45 m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID); 44 m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID);
46 LockAxisConstraint = null; 45 LockAxisConstraint = null;
@@ -69,18 +68,13 @@ public class BSActorLockAxis : BSActor
69 // If all the axis are free, we don't need to exist 68 // If all the axis are free, we don't need to exist
70 if (m_controllingPrim.LockedAxis == m_controllingPrim.LockedAxisFree) 69 if (m_controllingPrim.LockedAxis == m_controllingPrim.LockedAxisFree)
71 { 70 {
72 m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,allAxisFree,removing={1}", m_controllingPrim.LocalID, ActorName); 71 Enabled = false;
73 m_controllingPrim.PhysicalActors.RemoveAndRelease(ActorName);
74 return;
75 } 72 }
73
76 // If the object is physically active, add the axis locking constraint 74 // If the object is physically active, add the axis locking constraint
77 if (Enabled 75 if (isActive)
78 && m_controllingPrim.IsPhysicallyActive
79 && TryExperimentalLockAxisCode
80 && m_controllingPrim.LockedAxis != m_controllingPrim.LockedAxisFree)
81 { 76 {
82 if (LockAxisConstraint == null) 77 AddAxisLockConstraint();
83 AddAxisLockConstraint();
84 } 78 }
85 else 79 else
86 { 80 {
@@ -99,7 +93,7 @@ public class BSActorLockAxis : BSActor
99 // If a constraint is set up, remove it from the physical scene 93 // If a constraint is set up, remove it from the physical scene
100 RemoveAxisLockConstraint(); 94 RemoveAxisLockConstraint();
101 // Schedule a call before the next simulation step to restore the constraint. 95 // Schedule a call before the next simulation step to restore the constraint.
102 m_physicsScene.PostTaintObject(m_controllingPrim.LockedAxisActorName, m_controllingPrim.LocalID, delegate() 96 m_physicsScene.PostTaintObject("BSActorLockAxis:" + ActorName, m_controllingPrim.LocalID, delegate()
103 { 97 {
104 Refresh(); 98 Refresh();
105 }); 99 });
@@ -108,58 +102,61 @@ public class BSActorLockAxis : BSActor
108 102
109 private void AddAxisLockConstraint() 103 private void AddAxisLockConstraint()
110 { 104 {
111 // Lock that axis by creating a 6DOF constraint that has one end in the world and 105 if (LockAxisConstraint == null)
112 // the other in the object. 106 {
113 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817 107 // Lock that axis by creating a 6DOF constraint that has one end in the world and
114 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380 108 // the other in the object.
109 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817
110 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380
115 111
116 // Remove any existing axis constraint (just to be sure) 112 // Remove any existing axis constraint (just to be sure)
117 RemoveAxisLockConstraint(); 113 RemoveAxisLockConstraint();
118 114
119 BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(m_physicsScene.World, m_controllingPrim.PhysBody, 115 BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(m_physicsScene.World, m_controllingPrim.PhysBody,
120 OMV.Vector3.Zero, OMV.Quaternion.Identity, 116 OMV.Vector3.Zero, OMV.Quaternion.Identity,
121 false /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */); 117 false /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */);
122 LockAxisConstraint = axisConstrainer; 118 LockAxisConstraint = axisConstrainer;
123 m_physicsScene.Constraints.AddConstraint(LockAxisConstraint); 119 m_physicsScene.Constraints.AddConstraint(LockAxisConstraint);
124 120
125 // The constraint is tied to the world and oriented to the prim. 121 // The constraint is tied to the world and oriented to the prim.
126 122
127 // Free to move linearly in the region 123 // Free to move linearly in the region
128 OMV.Vector3 linearLow = OMV.Vector3.Zero; 124 OMV.Vector3 linearLow = OMV.Vector3.Zero;
129 OMV.Vector3 linearHigh = m_physicsScene.TerrainManager.DefaultRegionSize; 125 OMV.Vector3 linearHigh = m_physicsScene.TerrainManager.DefaultRegionSize;
130 axisConstrainer.SetLinearLimits(linearLow, linearHigh); 126 axisConstrainer.SetLinearLimits(linearLow, linearHigh);
131 127
132 // Angular with some axis locked 128 // Angular with some axis locked
133 float fPI = (float)Math.PI; 129 float fPI = (float)Math.PI;
134 OMV.Vector3 angularLow = new OMV.Vector3(-fPI, -fPI, -fPI); 130 OMV.Vector3 angularLow = new OMV.Vector3(-fPI, -fPI, -fPI);
135 OMV.Vector3 angularHigh = new OMV.Vector3(fPI, fPI, fPI); 131 OMV.Vector3 angularHigh = new OMV.Vector3(fPI, fPI, fPI);
136 if (m_controllingPrim.LockedAxis.X != 1f) 132 if (m_controllingPrim.LockedAxis.X != 1f)
137 { 133 {
138 angularLow.X = 0f; 134 angularLow.X = 0f;
139 angularHigh.X = 0f; 135 angularHigh.X = 0f;
140 } 136 }
141 if (m_controllingPrim.LockedAxis.Y != 1f) 137 if (m_controllingPrim.LockedAxis.Y != 1f)
142 { 138 {
143 angularLow.Y = 0f; 139 angularLow.Y = 0f;
144 angularHigh.Y = 0f; 140 angularHigh.Y = 0f;
145 } 141 }
146 if (m_controllingPrim.LockedAxis.Z != 1f) 142 if (m_controllingPrim.LockedAxis.Z != 1f)
147 { 143 {
148 angularLow.Z = 0f; 144 angularLow.Z = 0f;
149 angularHigh.Z = 0f; 145 angularHigh.Z = 0f;
150 } 146 }
151 if (!axisConstrainer.SetAngularLimits(angularLow, angularHigh)) 147 if (!axisConstrainer.SetAngularLimits(angularLow, angularHigh))
152 { 148 {
153 m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,failedSetAngularLimits", m_controllingPrim.LocalID); 149 m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,failedSetAngularLimits", m_controllingPrim.LocalID);
154 } 150 }
155 151
156 m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,create,linLow={1},linHi={2},angLow={3},angHi={4}", 152 m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,create,linLow={1},linHi={2},angLow={3},angHi={4}",
157 m_controllingPrim.LocalID, linearLow, linearHigh, angularLow, angularHigh); 153 m_controllingPrim.LocalID, linearLow, linearHigh, angularLow, angularHigh);
158 154
159 // Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo. 155 // Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo.
160 axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f); 156 axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f);
161 157
162 axisConstrainer.RecomputeConstraintVariables(m_controllingPrim.RawMass); 158 axisConstrainer.RecomputeConstraintVariables(m_controllingPrim.RawMass);
159 }
163 } 160 }
164 161
165 private void RemoveAxisLockConstraint() 162 private void RemoveAxisLockConstraint()
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs
new file mode 100755
index 0000000..56aacc5
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs
@@ -0,0 +1,158 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
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 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
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
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
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenSim.Region.Physics.Manager;
34
35using OMV = OpenMetaverse;
36
37namespace OpenSim.Region.Physics.BulletSPlugin
38{
39public class BSActorMoveToTarget : BSActor
40{
41 private BSVMotor m_targetMotor;
42
43 public BSActorMoveToTarget(BSScene physicsScene, BSPhysObject pObj, string actorName)
44 : base(physicsScene, pObj, actorName)
45 {
46 m_targetMotor = null;
47 m_physicsScene.DetailLog("{0},BSActorMoveToTarget,constructor", m_controllingPrim.LocalID);
48 }
49
50 // BSActor.isActive
51 public override bool isActive
52 {
53 get { return Enabled; }
54 }
55
56 // Release any connections and resources used by the actor.
57 // BSActor.Dispose()
58 public override void Dispose()
59 {
60 Enabled = false;
61 }
62
63 // Called when physical parameters (properties set in Bullet) need to be re-applied.
64 // Called at taint-time.
65 // BSActor.Refresh()
66 public override void Refresh()
67 {
68 m_physicsScene.DetailLog("{0},BSActorMoveToTarget,refresh,enabled={1},active={2},target={3},tau={4}",
69 m_controllingPrim.LocalID, Enabled, m_controllingPrim.MoveToTargetActive,
70 m_controllingPrim.MoveToTargetTarget, m_controllingPrim.MoveToTargetTau );
71
72 // If not active any more...
73 if (!m_controllingPrim.MoveToTargetActive)
74 {
75 Enabled = false;
76 }
77
78 if (isActive)
79 {
80 ActivateMoveToTarget();
81 }
82 else
83 {
84 DeactivateMoveToTarget();
85 }
86 }
87
88 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
89 // Register a prestep action to restore physical requirements before the next simulation step.
90 // Called at taint-time.
91 // BSActor.RemoveBodyDependencies()
92 public override void RemoveBodyDependencies()
93 {
94 // Nothing to do for the moveToTarget since it is all software at pre-step action time.
95 }
96
97 // If a hover motor has not been created, create one and start the hovering.
98 private void ActivateMoveToTarget()
99 {
100 if (m_targetMotor == null)
101 {
102 // We're taking over after this.
103 m_controllingPrim.ZeroMotion(true);
104
105 m_targetMotor = new BSVMotor("BSActorMoveToTargget.Activate",
106 m_controllingPrim.MoveToTargetTau, // timeScale
107 BSMotor.Infinite, // decay time scale
108 BSMotor.InfiniteVector, // friction timescale
109 1f // efficiency
110 );
111 m_targetMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages.
112 m_targetMotor.SetTarget(m_controllingPrim.MoveToTargetTarget);
113 m_targetMotor.SetCurrent(m_controllingPrim.RawPosition);
114
115 m_physicsScene.BeforeStep += Mover;
116 }
117 }
118
119 private void DeactivateMoveToTarget()
120 {
121 if (m_targetMotor != null)
122 {
123 m_physicsScene.BeforeStep -= Mover;
124 m_targetMotor = null;
125 }
126 }
127
128 // Called just before the simulation step. Update the vertical position for hoverness.
129 private void Mover(float timeStep)
130 {
131 // Don't do hovering while the object is selected.
132 if (!isActive)
133 return;
134
135 OMV.Vector3 origPosition = m_controllingPrim.RawPosition; // DEBUG DEBUG (for printout below)
136
137 // 'movePosition' is where we'd like the prim to be at this moment.
138 OMV.Vector3 movePosition = m_controllingPrim.RawPosition + m_targetMotor.Step(timeStep);
139
140 // If we are very close to our target, turn off the movement motor.
141 if (m_targetMotor.ErrorIsZero())
142 {
143 m_physicsScene.DetailLog("{0},BSActorMoveToTarget.Mover,zeroMovement,movePos={1},pos={2},mass={3}",
144 m_controllingPrim.LocalID, movePosition, m_controllingPrim.RawPosition, m_controllingPrim.Mass);
145 m_controllingPrim.ForcePosition = m_targetMotor.TargetValue;
146 // Setting the position does not cause the physics engine to generate a property update. Force it.
147 m_physicsScene.PE.PushUpdate(m_controllingPrim.PhysBody);
148 }
149 else
150 {
151 m_controllingPrim.ForcePosition = movePosition;
152 // Setting the position does not cause the physics engine to generate a property update. Force it.
153 m_physicsScene.PE.PushUpdate(m_controllingPrim.PhysBody);
154 }
155 m_physicsScene.DetailLog("{0},BSActorMoveToTarget.Mover,move,fromPos={1},movePos={2}", m_controllingPrim.LocalID, origPosition, movePosition);
156 }
157}
158}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs
new file mode 100755
index 0000000..3ad138d
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs
@@ -0,0 +1,137 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
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 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
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
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
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenSim.Region.Physics.Manager;
34
35using OMV = OpenMetaverse;
36
37namespace OpenSim.Region.Physics.BulletSPlugin
38{
39public class BSActorSetForce : BSActor
40{
41 BSFMotor m_forceMotor;
42
43 public BSActorSetForce(BSScene physicsScene, BSPhysObject pObj, string actorName)
44 : base(physicsScene, pObj, actorName)
45 {
46 m_forceMotor = null;
47 m_physicsScene.DetailLog("{0},BSActorSetForce,constructor", m_controllingPrim.LocalID);
48 }
49
50 // BSActor.isActive
51 public override bool isActive
52 {
53 get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
54 }
55
56 // Release any connections and resources used by the actor.
57 // BSActor.Dispose()
58 public override void Dispose()
59 {
60 Enabled = false;
61 }
62
63 // Called when physical parameters (properties set in Bullet) need to be re-applied.
64 // Called at taint-time.
65 // BSActor.Refresh()
66 public override void Refresh()
67 {
68 m_physicsScene.DetailLog("{0},BSActorSetForce,refresh", m_controllingPrim.LocalID);
69
70 // If not active any more, get rid of me (shouldn't ever happen, but just to be safe)
71 if (m_controllingPrim.RawForce == OMV.Vector3.Zero)
72 {
73 m_physicsScene.DetailLog("{0},BSActorSetForce,refresh,notSetForce,removing={1}", m_controllingPrim.LocalID, ActorName);
74 Enabled = false;
75 return;
76 }
77
78 // If the object is physically active, add the hoverer prestep action
79 if (isActive)
80 {
81 ActivateSetForce();
82 }
83 else
84 {
85 DeactivateSetForce();
86 }
87 }
88
89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
90 // Register a prestep action to restore physical requirements before the next simulation step.
91 // Called at taint-time.
92 // BSActor.RemoveBodyDependencies()
93 public override void RemoveBodyDependencies()
94 {
95 // Nothing to do for the hoverer since it is all software at pre-step action time.
96 }
97
98 // If a hover motor has not been created, create one and start the hovering.
99 private void ActivateSetForce()
100 {
101 if (m_forceMotor == null)
102 {
103 // A fake motor that might be used someday
104 m_forceMotor = new BSFMotor("setForce", 1f, 1f, 1f, 1f);
105
106 m_physicsScene.BeforeStep += Mover;
107 }
108 }
109
110 private void DeactivateSetForce()
111 {
112 if (m_forceMotor != null)
113 {
114 m_physicsScene.BeforeStep -= Mover;
115 m_forceMotor = null;
116 }
117 }
118
119 // Called just before the simulation step. Update the vertical position for hoverness.
120 private void Mover(float timeStep)
121 {
122 // Don't do force while the object is selected.
123 if (!isActive)
124 return;
125
126 m_physicsScene.DetailLog("{0},BSActorSetForce,preStep,force={1}", m_controllingPrim.LocalID, m_controllingPrim.RawForce);
127 if (m_controllingPrim.PhysBody.HasPhysicalBody)
128 {
129 m_physicsScene.PE.ApplyCentralForce(m_controllingPrim.PhysBody, m_controllingPrim.RawForce);
130 m_controllingPrim.ActivateIfPhysical(false);
131 }
132
133 // TODO:
134 }
135}
136}
137
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs
new file mode 100755
index 0000000..7a791ec
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs
@@ -0,0 +1,138 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
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 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
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
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
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenSim.Region.Physics.Manager;
34
35using OMV = OpenMetaverse;
36
37namespace OpenSim.Region.Physics.BulletSPlugin
38{
39public class BSActorSetTorque : BSActor
40{
41 BSFMotor m_torqueMotor;
42
43 public BSActorSetTorque(BSScene physicsScene, BSPhysObject pObj, string actorName)
44 : base(physicsScene, pObj, actorName)
45 {
46 m_torqueMotor = null;
47 m_physicsScene.DetailLog("{0},BSActorSetTorque,constructor", m_controllingPrim.LocalID);
48 }
49
50 // BSActor.isActive
51 public override bool isActive
52 {
53 get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
54 }
55
56 // Release any connections and resources used by the actor.
57 // BSActor.Dispose()
58 public override void Dispose()
59 {
60 Enabled = false;
61 }
62
63 // Called when physical parameters (properties set in Bullet) need to be re-applied.
64 // Called at taint-time.
65 // BSActor.Refresh()
66 public override void Refresh()
67 {
68 m_physicsScene.DetailLog("{0},BSActorSetTorque,refresh,torque={1}", m_controllingPrim.LocalID, m_controllingPrim.RawTorque);
69
70 // If not active any more, get rid of me (shouldn't ever happen, but just to be safe)
71 if (m_controllingPrim.RawTorque == OMV.Vector3.Zero)
72 {
73 m_physicsScene.DetailLog("{0},BSActorSetTorque,refresh,notSetTorque,disabling={1}", m_controllingPrim.LocalID, ActorName);
74 Enabled = false;
75 return;
76 }
77
78 // If the object is physically active, add the hoverer prestep action
79 if (isActive)
80 {
81 ActivateSetTorque();
82 }
83 else
84 {
85 DeactivateSetTorque();
86 }
87 }
88
89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
90 // Register a prestep action to restore physical requirements before the next simulation step.
91 // Called at taint-time.
92 // BSActor.RemoveBodyDependencies()
93 public override void RemoveBodyDependencies()
94 {
95 // Nothing to do for the hoverer since it is all software at pre-step action time.
96 }
97
98 // If a hover motor has not been created, create one and start the hovering.
99 private void ActivateSetTorque()
100 {
101 if (m_torqueMotor == null)
102 {
103 // A fake motor that might be used someday
104 m_torqueMotor = new BSFMotor("setTorque", 1f, 1f, 1f, 1f);
105
106 m_physicsScene.BeforeStep += Mover;
107 }
108 }
109
110 private void DeactivateSetTorque()
111 {
112 if (m_torqueMotor != null)
113 {
114 m_physicsScene.BeforeStep -= Mover;
115 m_torqueMotor = null;
116 }
117 }
118
119 // Called just before the simulation step. Update the vertical position for hoverness.
120 private void Mover(float timeStep)
121 {
122 // Don't do force while the object is selected.
123 if (!isActive)
124 return;
125
126 m_physicsScene.DetailLog("{0},BSActorSetTorque,preStep,force={1}", m_controllingPrim.LocalID, m_controllingPrim.RawTorque);
127 if (m_controllingPrim.PhysBody.HasPhysicalBody)
128 {
129 m_controllingPrim.AddAngularForce(m_controllingPrim.RawTorque, false, true);
130 m_controllingPrim.ActivateIfPhysical(false);
131 }
132
133 // TODO:
134 }
135}
136}
137
138
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
index 5a19ba4..12a8817 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
@@ -32,45 +32,72 @@ namespace OpenSim.Region.Physics.BulletSPlugin
32{ 32{
33public class BSActorCollection 33public class BSActorCollection
34{ 34{
35 private BSScene PhysicsScene { get; set; } 35 private BSScene m_physicsScene { get; set; }
36 private Dictionary<string, BSActor> m_actors; 36 private Dictionary<string, BSActor> m_actors;
37 37
38 public BSActorCollection(BSScene physicsScene) 38 public BSActorCollection(BSScene physicsScene)
39 { 39 {
40 PhysicsScene = physicsScene; 40 m_physicsScene = physicsScene;
41 m_actors = new Dictionary<string, BSActor>(); 41 m_actors = new Dictionary<string, BSActor>();
42 } 42 }
43 public void Add(string name, BSActor actor) 43 public void Add(string name, BSActor actor)
44 { 44 {
45 m_actors[name] = actor; 45 lock (m_actors)
46 {
47 if (!m_actors.ContainsKey(name))
48 {
49 m_actors[name] = actor;
50 }
51 }
46 } 52 }
47 public bool RemoveAndRelease(string name) 53 public bool RemoveAndRelease(string name)
48 { 54 {
49 bool ret = false; 55 bool ret = false;
50 if (m_actors.ContainsKey(name)) 56 lock (m_actors)
51 { 57 {
52 BSActor beingRemoved = m_actors[name]; 58 if (m_actors.ContainsKey(name))
53 beingRemoved.Dispose(); 59 {
54 m_actors.Remove(name); 60 BSActor beingRemoved = m_actors[name];
55 ret = true; 61 m_actors.Remove(name);
62 beingRemoved.Dispose();
63 ret = true;
64 }
56 } 65 }
57 return ret; 66 return ret;
58 } 67 }
59 public void Clear() 68 public void Clear()
60 { 69 {
61 Release(); 70 lock (m_actors)
62 m_actors.Clear(); 71 {
72 Release();
73 m_actors.Clear();
74 }
75 }
76 public void Dispose()
77 {
78 Clear();
63 } 79 }
64 public bool HasActor(string name) 80 public bool HasActor(string name)
65 { 81 {
66 return m_actors.ContainsKey(name); 82 return m_actors.ContainsKey(name);
67 } 83 }
84 public bool TryGetActor(string actorName, out BSActor theActor)
85 {
86 return m_actors.TryGetValue(actorName, out theActor);
87 }
68 public void ForEachActor(Action<BSActor> act) 88 public void ForEachActor(Action<BSActor> act)
69 { 89 {
70 foreach (KeyValuePair<string, BSActor> kvp in m_actors) 90 lock (m_actors)
71 act(kvp.Value); 91 {
92 foreach (KeyValuePair<string, BSActor> kvp in m_actors)
93 act(kvp.Value);
94 }
72 } 95 }
73 96
97 public void Enable(bool enabl)
98 {
99 ForEachActor(a => a.SetEnabled(enabl));
100 }
74 public void Release() 101 public void Release()
75 { 102 {
76 ForEachActor(a => a.Dispose()); 103 ForEachActor(a => a.Dispose());
@@ -98,7 +125,7 @@ public abstract class BSActor
98{ 125{
99 protected BSScene m_physicsScene { get; private set; } 126 protected BSScene m_physicsScene { get; private set; }
100 protected BSPhysObject m_controllingPrim { get; private set; } 127 protected BSPhysObject m_controllingPrim { get; private set; }
101 protected bool Enabled { get; set; } 128 public virtual bool Enabled { get; set; }
102 public string ActorName { get; private set; } 129 public string ActorName { get; private set; }
103 130
104 public BSActor(BSScene physicsScene, BSPhysObject pObj, string actorName) 131 public BSActor(BSScene physicsScene, BSPhysObject pObj, string actorName)
@@ -114,8 +141,10 @@ public abstract class BSActor
114 { 141 {
115 get { return Enabled; } 142 get { return Enabled; }
116 } 143 }
117 // Turn the actor on an off. 144
118 public virtual void Enable(bool setEnabled) 145 // Turn the actor on an off. Only used by ActorCollection to set all enabled/disabled.
146 // Anyone else should assign true/false to 'Enabled'.
147 public void SetEnabled(bool setEnabled)
119 { 148 {
120 Enabled = setEnabled; 149 Enabled = setEnabled;
121 } 150 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 25be416..a0d58d3 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -46,9 +46,6 @@ public sealed class BSCharacter : BSPhysObject
46 private OMV.Vector3 _position; 46 private OMV.Vector3 _position;
47 private float _mass; 47 private float _mass;
48 private float _avatarVolume; 48 private float _avatarVolume;
49 private OMV.Vector3 _force;
50 private OMV.Vector3 _velocity;
51 private OMV.Vector3 _torque;
52 private float _collisionScore; 49 private float _collisionScore;
53 private OMV.Vector3 _acceleration; 50 private OMV.Vector3 _acceleration;
54 private OMV.Quaternion _orientation; 51 private OMV.Quaternion _orientation;
@@ -61,17 +58,13 @@ public sealed class BSCharacter : BSPhysObject
61 private OMV.Vector3 _rotationalVelocity; 58 private OMV.Vector3 _rotationalVelocity;
62 private bool _kinematic; 59 private bool _kinematic;
63 private float _buoyancy; 60 private float _buoyancy;
64 private bool _isStationaryStanding; // true is standing on a stationary object
65 61
66 private BSVMotor _velocityMotor; 62 private BSActorAvatarMove m_moveActor;
63 private const string AvatarMoveActorName = "BSCharacter.AvatarMove";
67 64
68 private OMV.Vector3 _PIDTarget; 65 private OMV.Vector3 _PIDTarget;
69 private bool _usePID; 66 private bool _usePID;
70 private float _PIDTau; 67 private float _PIDTau;
71 private bool _useHoverPID;
72 private float _PIDHoverHeight;
73 private PIDHoverType _PIDHoverType;
74 private float _PIDHoverTao;
75 68
76 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) 69 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
77 : base(parent_scene, localID, avName, "BSCharacter") 70 : base(parent_scene, localID, avName, "BSCharacter")
@@ -81,11 +74,10 @@ public sealed class BSCharacter : BSPhysObject
81 74
82 _flying = isFlying; 75 _flying = isFlying;
83 _orientation = OMV.Quaternion.Identity; 76 _orientation = OMV.Quaternion.Identity;
84 _velocity = OMV.Vector3.Zero; 77 RawVelocity = OMV.Vector3.Zero;
85 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 78 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
86 Friction = BSParam.AvatarStandingFriction; 79 Friction = BSParam.AvatarStandingFriction;
87 Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor; 80 Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor;
88 _isStationaryStanding = false;
89 81
90 // Old versions of ScenePresence passed only the height. If width and/or depth are zero, 82 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
91 // replace with the default values. 83 // replace with the default values.
@@ -99,7 +91,12 @@ public sealed class BSCharacter : BSPhysObject
99 // set _avatarVolume and _mass based on capsule size, _density and Scale 91 // set _avatarVolume and _mass based on capsule size, _density and Scale
100 ComputeAvatarVolumeAndMass(); 92 ComputeAvatarVolumeAndMass();
101 93
102 SetupMovementMotor(); 94 // The avatar's movement is controlled by this motor that speeds up and slows down
95 // the avatar seeking to reach the motor's target speed.
96 // This motor runs as a prestep action for the avatar so it will keep the avatar
97 // standing as well as moving. Destruction of the avatar will destroy the pre-step action.
98 m_moveActor = new BSActorAvatarMove(PhysicsScene, this, AvatarMoveActorName);
99 PhysicalActors.Add(AvatarMoveActorName, m_moveActor);
103 100
104 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", 101 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
105 LocalID, _size, Scale, Density, _avatarVolume, RawMass); 102 LocalID, _size, Scale, Density, _avatarVolume, RawMass);
@@ -139,10 +136,10 @@ public sealed class BSCharacter : BSPhysObject
139 ForcePosition = _position; 136 ForcePosition = _position;
140 137
141 // Set the velocity 138 // Set the velocity
142 _velocityMotor.Reset(); 139 if (m_moveActor != null)
143 _velocityMotor.SetTarget(_velocity); 140 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, false);
144 _velocityMotor.SetCurrent(_velocity); 141
145 ForceVelocity = _velocity; 142 ForceVelocity = RawVelocity;
146 143
147 // This will enable or disable the flying buoyancy of the avatar. 144 // This will enable or disable the flying buoyancy of the avatar.
148 // Needs to be reset especially when an avatar is recreated after crossing a region boundry. 145 // Needs to be reset especially when an avatar is recreated after crossing a region boundry.
@@ -163,6 +160,9 @@ public sealed class BSCharacter : BSPhysObject
163 // Make so capsule does not fall over 160 // Make so capsule does not fall over
164 PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero); 161 PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero);
165 162
163 // The avatar mover sets some parameters.
164 PhysicalActors.Refresh();
165
166 PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT); 166 PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT);
167 167
168 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); 168 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody);
@@ -176,162 +176,6 @@ public sealed class BSCharacter : BSPhysObject
176 PhysBody.ApplyCollisionMask(PhysicsScene); 176 PhysBody.ApplyCollisionMask(PhysicsScene);
177 } 177 }
178 178
179 // The avatar's movement is controlled by this motor that speeds up and slows down
180 // the avatar seeking to reach the motor's target speed.
181 // This motor runs as a prestep action for the avatar so it will keep the avatar
182 // standing as well as moving. Destruction of the avatar will destroy the pre-step action.
183 private void SetupMovementMotor()
184 {
185 // Infinite decay and timescale values so motor only changes current to target values.
186 _velocityMotor = new BSVMotor("BSCharacter.Velocity",
187 0.2f, // time scale
188 BSMotor.Infinite, // decay time scale
189 BSMotor.InfiniteVector, // friction timescale
190 1f // efficiency
191 );
192 // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
193
194 RegisterPreStepAction("BSCharactor.Movement", LocalID, delegate(float timeStep)
195 {
196 // TODO: Decide if the step parameters should be changed depending on the avatar's
197 // state (flying, colliding, ...). There is code in ODE to do this.
198
199 // COMMENTARY: when the user is making the avatar walk, except for falling, the velocity
200 // specified for the avatar is the one that should be used. For falling, if the avatar
201 // is not flying and is not colliding then it is presumed to be falling and the Z
202 // component is not fooled with (thus allowing gravity to do its thing).
203 // When the avatar is standing, though, the user has specified a velocity of zero and
204 // the avatar should be standing. But if the avatar is pushed by something in the world
205 // (raising elevator platform, moving vehicle, ...) the avatar should be allowed to
206 // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity
207 // errors can creap in and the avatar will slowly float off in some direction.
208 // So, the problem is that, when an avatar is standing, we cannot tell creaping error
209 // from real pushing.
210 // The code below uses whether the collider is static or moving to decide whether to zero motion.
211
212 _velocityMotor.Step(timeStep);
213 _isStationaryStanding = false;
214
215 // If we're not supposed to be moving, make sure things are zero.
216 if (_velocityMotor.ErrorIsZero() && _velocityMotor.TargetValue == OMV.Vector3.Zero)
217 {
218 // The avatar shouldn't be moving
219 _velocityMotor.Zero();
220
221 if (IsColliding)
222 {
223 // If we are colliding with a stationary object, presume we're standing and don't move around
224 if (!ColliderIsMoving)
225 {
226 DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", LocalID);
227 _isStationaryStanding = true;
228 ZeroMotion(true /* inTaintTime */);
229 }
230
231 // Standing has more friction on the ground
232 if (Friction != BSParam.AvatarStandingFriction)
233 {
234 Friction = BSParam.AvatarStandingFriction;
235 PhysicsScene.PE.SetFriction(PhysBody, Friction);
236 }
237 }
238 else
239 {
240 if (Flying)
241 {
242 // Flying and not collising and velocity nearly zero.
243 ZeroMotion(true /* inTaintTime */);
244 }
245 }
246
247 DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", LocalID, _velocityMotor.TargetValue, IsColliding);
248 }
249 else
250 {
251 // Supposed to be moving.
252 OMV.Vector3 stepVelocity = _velocityMotor.CurrentValue;
253
254 if (Friction != BSParam.AvatarFriction)
255 {
256 // Probably starting up walking. Set friction to moving friction.
257 Friction = BSParam.AvatarFriction;
258 PhysicsScene.PE.SetFriction(PhysBody, Friction);
259 }
260
261 // If falling, we keep the world's downward vector no matter what the other axis specify.
262 // The check for _velocity.Z < 0 makes jumping work (temporary upward force).
263 if (!Flying && !IsColliding)
264 {
265 if (_velocity.Z < 0)
266 stepVelocity.Z = _velocity.Z;
267 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
268 }
269
270 // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
271 OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass;
272
273 // Should we check for move force being small and forcing velocity to zero?
274
275 // Add special movement force to allow avatars to walk up stepped surfaces.
276 moveForce += WalkUpStairs();
277
278 DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
279 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce);
280 }
281 });
282 }
283
284 // Decide if the character is colliding with a low object and compute a force to pop the
285 // avatar up so it can walk up and over the low objects.
286 private OMV.Vector3 WalkUpStairs()
287 {
288 OMV.Vector3 ret = OMV.Vector3.Zero;
289
290 // This test is done if moving forward, not flying and is colliding with something.
291 // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
292 // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
293 if (IsColliding && !Flying && TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */)
294 {
295 // The range near the character's feet where we will consider stairs
296 float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f;
297 float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
298
299 // Look for a collision point that is near the character's feet and is oriented the same as the charactor is
300 foreach (KeyValuePair<uint, ContactPoint> kvp in CollisionsLastTick.m_objCollisionList)
301 {
302 // Don't care about collisions with the terrain
303 if (kvp.Key > PhysicsScene.TerrainManager.HighestTerrainID)
304 {
305 OMV.Vector3 touchPosition = kvp.Value.Position;
306 // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
307 // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
308 if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
309 {
310 // This contact is within the 'near the feet' range.
311 // The normal should be our contact point to the object so it is pointing away
312 // thus the difference between our facing orientation and the normal should be small.
313 OMV.Vector3 directionFacing = OMV.Vector3.UnitX * RawOrientation;
314 OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal);
315 float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
316 if (diff < BSParam.AvatarStepApproachFactor)
317 {
318 // Found the stairs contact point. Push up a little to raise the character.
319 float upForce = (touchPosition.Z - nearFeetHeightMin) * Mass * BSParam.AvatarStepForceFactor;
320 ret = new OMV.Vector3(0f, 0f, upForce);
321
322 // Also move the avatar up for the new height
323 OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f);
324 ForcePosition = RawPosition + displacement;
325 }
326 DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}",
327 LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret);
328 }
329 }
330 }
331 }
332
333 return ret;
334 }
335 179
336 public override void RequestPhysicsterseUpdate() 180 public override void RequestPhysicsterseUpdate()
337 { 181 {
@@ -403,7 +247,7 @@ public sealed class BSCharacter : BSPhysObject
403 // Called at taint time! 247 // Called at taint time!
404 public override void ZeroMotion(bool inTaintTime) 248 public override void ZeroMotion(bool inTaintTime)
405 { 249 {
406 _velocity = OMV.Vector3.Zero; 250 RawVelocity = OMV.Vector3.Zero;
407 _acceleration = OMV.Vector3.Zero; 251 _acceleration = OMV.Vector3.Zero;
408 _rotationalVelocity = OMV.Vector3.Zero; 252 _rotationalVelocity = OMV.Vector3.Zero;
409 253
@@ -542,15 +386,15 @@ public sealed class BSCharacter : BSPhysObject
542 } 386 }
543 387
544 public override OMV.Vector3 Force { 388 public override OMV.Vector3 Force {
545 get { return _force; } 389 get { return RawForce; }
546 set { 390 set {
547 _force = value; 391 RawForce = value;
548 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); 392 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
549 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() 393 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate()
550 { 394 {
551 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); 395 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce);
552 if (PhysBody.HasPhysicalBody) 396 if (PhysBody.HasPhysicalBody)
553 PhysicsScene.PE.SetObjectForce(PhysBody, _force); 397 PhysicsScene.PE.SetObjectForce(PhysBody, RawForce);
554 }); 398 });
555 } 399 }
556 } 400 }
@@ -573,7 +417,7 @@ public sealed class BSCharacter : BSPhysObject
573 { 417 {
574 get 418 get
575 { 419 {
576 return m_targetVelocity; 420 return base.m_targetVelocity;
577 } 421 }
578 set 422 set
579 { 423 {
@@ -583,51 +427,39 @@ public sealed class BSCharacter : BSPhysObject
583 if (_setAlwaysRun) 427 if (_setAlwaysRun)
584 targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f); 428 targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f);
585 429
586 PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate() 430 if (m_moveActor != null)
587 { 431 m_moveActor.SetVelocityAndTarget(RawVelocity, targetVel, false /* inTaintTime */);
588 _velocityMotor.Reset();
589 _velocityMotor.SetTarget(targetVel);
590 _velocityMotor.SetCurrent(_velocity);
591 _velocityMotor.Enabled = true;
592 });
593 } 432 }
594 } 433 }
595 public override OMV.Vector3 RawVelocity
596 {
597 get { return _velocity; }
598 set { _velocity = value; }
599 }
600 // Directly setting velocity means this is what the user really wants now. 434 // Directly setting velocity means this is what the user really wants now.
601 public override OMV.Vector3 Velocity { 435 public override OMV.Vector3 Velocity {
602 get { return _velocity; } 436 get { return RawVelocity; }
603 set { 437 set {
604 _velocity = value; 438 RawVelocity = value;
605 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 439 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity);
606 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() 440 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate()
607 { 441 {
608 _velocityMotor.Reset(); 442 if (m_moveActor != null)
609 _velocityMotor.SetCurrent(_velocity); 443 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */);
610 _velocityMotor.SetTarget(_velocity);
611 _velocityMotor.Enabled = false;
612 444
613 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); 445 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, RawVelocity);
614 ForceVelocity = _velocity; 446 ForceVelocity = RawVelocity;
615 }); 447 });
616 } 448 }
617 } 449 }
618 public override OMV.Vector3 ForceVelocity { 450 public override OMV.Vector3 ForceVelocity {
619 get { return _velocity; } 451 get { return RawVelocity; }
620 set { 452 set {
621 PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity"); 453 PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity");
622 454
623 _velocity = value; 455 RawVelocity = value;
624 PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); 456 PhysicsScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
625 PhysicsScene.PE.Activate(PhysBody, true); 457 PhysicsScene.PE.Activate(PhysBody, true);
626 } 458 }
627 } 459 }
628 public override OMV.Vector3 Torque { 460 public override OMV.Vector3 Torque {
629 get { return _torque; } 461 get { return RawTorque; }
630 set { _torque = value; 462 set { RawTorque = value;
631 } 463 }
632 } 464 }
633 public override float CollisionScore { 465 public override float CollisionScore {
@@ -783,27 +615,6 @@ public sealed class BSCharacter : BSPhysObject
783 set { _PIDTau = value; } 615 set { _PIDTau = value; }
784 } 616 }
785 617
786 // Used for llSetHoverHeight and maybe vehicle height
787 // Hover Height will override MoveTo target's Z
788 public override bool PIDHoverActive {
789 set { _useHoverPID = value; }
790 }
791 public override float PIDHoverHeight {
792 set { _PIDHoverHeight = value; }
793 }
794 public override PIDHoverType PIDHoverType {
795 set { _PIDHoverType = value; }
796 }
797 public override float PIDHoverTau {
798 set { _PIDHoverTao = value; }
799 }
800
801 // For RotLookAt
802 public override OMV.Quaternion APIDTarget { set { return; } }
803 public override bool APIDActive { set { return; } }
804 public override float APIDStrength { set { return; } }
805 public override float APIDDamping { set { return; } }
806
807 public override void AddForce(OMV.Vector3 force, bool pushforce) 618 public override void AddForce(OMV.Vector3 force, bool pushforce)
808 { 619 {
809 // Since this force is being applied in only one step, make this a force per second. 620 // Since this force is being applied in only one step, make this a force per second.
@@ -833,7 +644,7 @@ public sealed class BSCharacter : BSPhysObject
833 } 644 }
834 } 645 }
835 646
836 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 647 public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
837 } 648 }
838 public override void SetMomentum(OMV.Vector3 momentum) { 649 public override void SetMomentum(OMV.Vector3 momentum) {
839 } 650 }
@@ -887,7 +698,7 @@ public sealed class BSCharacter : BSPhysObject
887 public override void UpdateProperties(EntityProperties entprop) 698 public override void UpdateProperties(EntityProperties entprop)
888 { 699 {
889 // Don't change position if standing on a stationary object. 700 // Don't change position if standing on a stationary object.
890 if (!_isStationaryStanding) 701 if (!IsStationary)
891 _position = entprop.Position; 702 _position = entprop.Position;
892 703
893 _orientation = entprop.Rotation; 704 _orientation = entprop.Rotation;
@@ -896,8 +707,8 @@ public sealed class BSCharacter : BSPhysObject
896 // and will send agent updates to the clients if velocity changes by more than 707 // and will send agent updates to the clients if velocity changes by more than
897 // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many 708 // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many
898 // extra updates. 709 // extra updates.
899 if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f)) 710 if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.1f))
900 _velocity = entprop.Velocity; 711 RawVelocity = entprop.Velocity;
901 712
902 _acceleration = entprop.Acceleration; 713 _acceleration = entprop.Acceleration;
903 _rotationalVelocity = entprop.RotationalVelocity; 714 _rotationalVelocity = entprop.RotationalVelocity;
@@ -920,7 +731,7 @@ public sealed class BSCharacter : BSPhysObject
920 // base.RequestPhysicsterseUpdate(); 731 // base.RequestPhysicsterseUpdate();
921 732
922 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 733 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
923 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 734 LocalID, _position, _orientation, RawVelocity, _acceleration, _rotationalVelocity);
924 } 735 }
925} 736}
926} 737}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 0fd1f73..612c68b 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -1358,6 +1358,35 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1358 // If vertical attaction timescale is reasonable 1358 // If vertical attaction timescale is reasonable
1359 if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1359 if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1360 { 1360 {
1361 //Another formula to try got from :
1362 //http://answers.unity3d.com/questions/10425/how-to-stabilize-angular-motion-alignment-of-hover.html
1363
1364 Vector3 VehicleUpAxis = Vector3.UnitZ * VehicleOrientation;
1365
1366 // Flipping what was originally a timescale into a speed variable and then multiplying it by 2
1367 // since only computing half the distance between the angles.
1368 float VerticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f;
1369
1370 // Make a prediction of where the up axis will be when this is applied rather then where it is now as
1371 // this makes for a smoother adjustment and less fighting between the various forces.
1372 Vector3 predictedUp = VehicleUpAxis * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
1373
1374 // This is only half the distance to the target so it will take 2 seconds to complete the turn.
1375 Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ);
1376
1377 // Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared
1378 Vector3 vertContributionV = torqueVector * VerticalAttractionSpeed * VerticalAttractionSpeed;
1379
1380 VehicleRotationalVelocity += vertContributionV;
1381
1382 VDetailLog("{0}, MoveAngular,verticalAttraction,UpAxis={1},PredictedUp={2},torqueVector={3},contrib={4}",
1383 ControllingPrim.LocalID,
1384 VehicleUpAxis,
1385 predictedUp,
1386 torqueVector,
1387 vertContributionV);
1388 //=====================================================================
1389 /*
1361 // Possible solution derived from a discussion at: 1390 // Possible solution derived from a discussion at:
1362 // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no 1391 // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
1363 1392
@@ -1392,6 +1421,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1392 differenceAngle, 1421 differenceAngle,
1393 correctionRotation, 1422 correctionRotation,
1394 vertContributionV); 1423 vertContributionV);
1424 */
1395 1425
1396 // =================================================================== 1426 // ===================================================================
1397 /* 1427 /*
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 385ed9e..06df85e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -86,6 +86,7 @@ public static class BSParam
86 public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes 86 public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
87 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects 87 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
88 public static bool ShouldRemoveZeroWidthTriangles { get; private set; } 88 public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
89 public static bool ShouldUseBulletHACD { get; set; }
89 90
90 public static float TerrainImplementation { get; private set; } 91 public static float TerrainImplementation { get; private set; }
91 public static int TerrainMeshMagnification { get; private set; } 92 public static int TerrainMeshMagnification { get; private set; }
@@ -149,6 +150,15 @@ public static class BSParam
149 public static float CSHullVolumeConservationThresholdPercent { get; private set; } 150 public static float CSHullVolumeConservationThresholdPercent { get; private set; }
150 public static int CSHullMaxVertices { get; private set; } 151 public static int CSHullMaxVertices { get; private set; }
151 public static float CSHullMaxSkinWidth { get; private set; } 152 public static float CSHullMaxSkinWidth { get; private set; }
153 public static float BHullMaxVerticesPerHull { get; private set; } // 100
154 public static float BHullMinClusters { get; private set; } // 2
155 public static float BHullCompacityWeight { get; private set; } // 0.1
156 public static float BHullVolumeWeight { get; private set; } // 0.0
157 public static float BHullConcavity { get; private set; } // 100
158 public static bool BHullAddExtraDistPoints { get; private set; } // false
159 public static bool BHullAddNeighboursDistPoints { get; private set; } // false
160 public static bool BHullAddFacesPoints { get; private set; } // false
161 public static bool BHullShouldAdjustCollisionMargin { get; private set; } // false
152 162
153 // Linkset implementation parameters 163 // Linkset implementation parameters
154 public static float LinksetImplementation { get; private set; } 164 public static float LinksetImplementation { get; private set; }
@@ -325,6 +335,10 @@ public static class BSParam
325 true, 335 true,
326 (s) => { return ShouldRemoveZeroWidthTriangles; }, 336 (s) => { return ShouldRemoveZeroWidthTriangles; },
327 (s,v) => { ShouldRemoveZeroWidthTriangles = v; } ), 337 (s,v) => { ShouldRemoveZeroWidthTriangles = v; } ),
338 new ParameterDefn<bool>("ShouldUseBulletHACD", "If true, use the Bullet version of HACD",
339 false,
340 (s) => { return ShouldUseBulletHACD; },
341 (s,v) => { ShouldUseBulletHACD = v; } ),
328 342
329 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions", 343 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
330 5, 344 5,
@@ -663,10 +677,47 @@ public static class BSParam
663 (s) => { return CSHullMaxVertices; }, 677 (s) => { return CSHullMaxVertices; },
664 (s,v) => { CSHullMaxVertices = v; } ), 678 (s,v) => { CSHullMaxVertices = v; } ),
665 new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.", 679 new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.",
666 0, 680 0f,
667 (s) => { return CSHullMaxSkinWidth; }, 681 (s) => { return CSHullMaxSkinWidth; },
668 (s,v) => { CSHullMaxSkinWidth = v; } ), 682 (s,v) => { CSHullMaxSkinWidth = v; } ),
669 683
684 new ParameterDefn<float>("BHullMaxVerticesPerHull", "Bullet impl: max number of vertices per created hull",
685 100f,
686 (s) => { return BHullMaxVerticesPerHull; },
687 (s,v) => { BHullMaxVerticesPerHull = v; } ),
688 new ParameterDefn<float>("BHullMinClusters", "Bullet impl: minimum number of hulls to create per mesh",
689 2f,
690 (s) => { return BHullMinClusters; },
691 (s,v) => { BHullMinClusters = v; } ),
692 new ParameterDefn<float>("BHullCompacityWeight", "Bullet impl: weight factor for how compact to make hulls",
693 2f,
694 (s) => { return BHullCompacityWeight; },
695 (s,v) => { BHullCompacityWeight = v; } ),
696 new ParameterDefn<float>("BHullVolumeWeight", "Bullet impl: weight factor for volume in created hull",
697 0.1f,
698 (s) => { return BHullVolumeWeight; },
699 (s,v) => { BHullVolumeWeight = v; } ),
700 new ParameterDefn<float>("BHullConcavity", "Bullet impl: weight factor for how convex a created hull can be",
701 100f,
702 (s) => { return BHullConcavity; },
703 (s,v) => { BHullConcavity = v; } ),
704 new ParameterDefn<bool>("BHullAddExtraDistPoints", "Bullet impl: whether to add extra vertices for long distance vectors",
705 false,
706 (s) => { return BHullAddExtraDistPoints; },
707 (s,v) => { BHullAddExtraDistPoints = v; } ),
708 new ParameterDefn<bool>("BHullAddNeighboursDistPoints", "Bullet impl: whether to add extra vertices between neighbor hulls",
709 false,
710 (s) => { return BHullAddNeighboursDistPoints; },
711 (s,v) => { BHullAddNeighboursDistPoints = v; } ),
712 new ParameterDefn<bool>("BHullAddFacesPoints", "Bullet impl: whether to add extra vertices to break up hull faces",
713 false,
714 (s) => { return BHullAddFacesPoints; },
715 (s,v) => { BHullAddFacesPoints = v; } ),
716 new ParameterDefn<bool>("BHullShouldAdjustCollisionMargin", "Bullet impl: whether to shrink resulting hulls to account for collision margin",
717 false,
718 (s) => { return BHullShouldAdjustCollisionMargin; },
719 (s,v) => { BHullShouldAdjustCollisionMargin = v; } ),
720
670 new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", 721 new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
671 (float)BSLinkset.LinksetImplementation.Compound, 722 (float)BSLinkset.LinksetImplementation.Compound,
672 (s) => { return LinksetImplementation; }, 723 (s) => { return LinksetImplementation; },
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 98ea833..98eb4ca 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -43,7 +43,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
43 * VariableName: used by the simulator and performs taint operations, etc 43 * VariableName: used by the simulator and performs taint operations, etc
44 * RawVariableName: direct reference to the BulletSim storage for the variable value 44 * RawVariableName: direct reference to the BulletSim storage for the variable value
45 * ForceVariableName: direct reference (store and fetch) to the value in the physics engine. 45 * ForceVariableName: direct reference (store and fetch) to the value in the physics engine.
46 * The last two (and certainly the last one) should be referenced only in taint-time. 46 * The last one should only be referenced in taint-time.
47 */ 47 */
48 48
49/* 49/*
@@ -84,6 +84,7 @@ public abstract class BSPhysObject : PhysicsActor
84 // Initialize variables kept in base. 84 // Initialize variables kept in base.
85 GravModifier = 1.0f; 85 GravModifier = 1.0f;
86 Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity); 86 Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity);
87 HoverActive = false;
87 88
88 // We don't have any physical representation yet. 89 // We don't have any physical representation yet.
89 PhysBody = new BulletBody(localID); 90 PhysBody = new BulletBody(localID);
@@ -110,11 +111,10 @@ public abstract class BSPhysObject : PhysicsActor
110 // Tell the object to clean up. 111 // Tell the object to clean up.
111 public virtual void Destroy() 112 public virtual void Destroy()
112 { 113 {
113 UnRegisterAllPreStepActions(); 114 PhysicalActors.Enable(false);
114 UnRegisterAllPostStepActions();
115 PhysicsScene.TaintedObject("BSPhysObject.Destroy", delegate() 115 PhysicsScene.TaintedObject("BSPhysObject.Destroy", delegate()
116 { 116 {
117 PhysicalActors.Release(); 117 PhysicalActors.Dispose();
118 }); 118 });
119 } 119 }
120 120
@@ -203,15 +203,48 @@ public abstract class BSPhysObject : PhysicsActor
203 public abstract OMV.Quaternion RawOrientation { get; set; } 203 public abstract OMV.Quaternion RawOrientation { get; set; }
204 public abstract OMV.Quaternion ForceOrientation { get; set; } 204 public abstract OMV.Quaternion ForceOrientation { get; set; }
205 205
206 public abstract OMV.Vector3 RawVelocity { get; set; } 206 public OMV.Vector3 RawVelocity { get; set; }
207 public abstract OMV.Vector3 ForceVelocity { get; set; } 207 public abstract OMV.Vector3 ForceVelocity { get; set; }
208 208
209 public OMV.Vector3 RawForce { get; set; }
210 public OMV.Vector3 RawTorque { get; set; }
211 public override void AddAngularForce(OMV.Vector3 force, bool pushforce)
212 {
213 AddAngularForce(force, pushforce, false);
214 }
215 public abstract void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime);
216
209 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } 217 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
210 218
211 public abstract float ForceBuoyancy { get; set; } 219 public abstract float ForceBuoyancy { get; set; }
212 220
213 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } 221 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
214 222
223 public override bool PIDActive { set { MoveToTargetActive = value; } }
224 public override OMV.Vector3 PIDTarget { set { MoveToTargetTarget = value; } }
225 public override float PIDTau { set { MoveToTargetTau = value; } }
226
227 public bool MoveToTargetActive { get; set; }
228 public OMV.Vector3 MoveToTargetTarget { get; set; }
229 public float MoveToTargetTau { get; set; }
230
231 // Used for llSetHoverHeight and maybe vehicle height. Hover Height will override MoveTo target's Z
232 public override bool PIDHoverActive { set { HoverActive = value; } }
233 public override float PIDHoverHeight { set { HoverHeight = value; } }
234 public override PIDHoverType PIDHoverType { set { HoverType = value; } }
235 public override float PIDHoverTau { set { HoverTau = value; } }
236
237 public bool HoverActive { get; set; }
238 public float HoverHeight { get; set; }
239 public PIDHoverType HoverType { get; set; }
240 public float HoverTau { get; set; }
241
242 // For RotLookAt
243 public override OMV.Quaternion APIDTarget { set { return; } }
244 public override bool APIDActive { set { return; } }
245 public override float APIDStrength { set { return; } }
246 public override float APIDDamping { set { return; } }
247
215 // The current velocity forward 248 // The current velocity forward
216 public virtual float ForwardSpeed 249 public virtual float ForwardSpeed
217 { 250 {
@@ -237,7 +270,51 @@ public abstract class BSPhysObject : PhysicsActor
237 270
238 public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free. 271 public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free.
239 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free 272 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free
240 public readonly String LockedAxisActorName = "BSPrim.LockedAxis"; 273
274 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
275 // they need waking up when parameters are changed.
276 // Called in taint-time!!
277 public void ActivateIfPhysical(bool forceIt)
278 {
279 if (IsPhysical && PhysBody.HasPhysicalBody)
280 PhysicsScene.PE.Activate(PhysBody, forceIt);
281 }
282
283 // 'actors' act on the physical object to change or constrain its motion. These can range from
284 // hovering to complex vehicle motion.
285 // May be called at non-taint time as this just adds the actor to the action list and the real
286 // work is done during the simulation step.
287 // Note that, if the actor is already in the list and we are disabling same, the actor is just left
288 // in the list disabled.
289 public delegate BSActor CreateActor();
290 public void EnableActor(bool enableActor, string actorName, CreateActor creator)
291 {
292 lock (PhysicalActors)
293 {
294 BSActor theActor;
295 if (PhysicalActors.TryGetActor(actorName, out theActor))
296 {
297 // The actor already exists so just turn it on or off
298 DetailLog("{0},BSPhysObject.EnableActor,enablingExistingActor,name={1},enable={2}", LocalID, actorName, enableActor);
299 theActor.Enabled = enableActor;
300 }
301 else
302 {
303 // The actor does not exist. If it should, create it.
304 if (enableActor)
305 {
306 DetailLog("{0},BSPhysObject.EnableActor,creatingActor,name={1}", LocalID, actorName);
307 theActor = creator();
308 PhysicalActors.Add(actorName, theActor);
309 theActor.Enabled = true;
310 }
311 else
312 {
313 DetailLog("{0},BSPhysObject.EnableActor,notCreatingActorSinceNotEnabled,name={1}", LocalID, actorName);
314 }
315 }
316 }
317 }
241 318
242 #region Collisions 319 #region Collisions
243 320
@@ -255,7 +332,9 @@ public abstract class BSPhysObject : PhysicsActor
255 protected CollisionFlags CurrentCollisionFlags { get; set; } 332 protected CollisionFlags CurrentCollisionFlags { get; set; }
256 // On a collision, check the collider and remember if the last collider was moving 333 // On a collision, check the collider and remember if the last collider was moving
257 // Used to modify the standing of avatars (avatars on stationary things stand still) 334 // Used to modify the standing of avatars (avatars on stationary things stand still)
258 protected bool ColliderIsMoving; 335 public bool ColliderIsMoving;
336 // Used by BSCharacter to manage standing (and not slipping)
337 public bool IsStationary;
259 338
260 // Count of collisions for this object 339 // Count of collisions for this object
261 protected long CollisionAccumulation { get; set; } 340 protected long CollisionAccumulation { get; set; }
@@ -293,7 +372,7 @@ public abstract class BSPhysObject : PhysicsActor
293 protected CollisionEventUpdate CollisionCollection; 372 protected CollisionEventUpdate CollisionCollection;
294 // Remember collisions from last tick for fancy collision based actions 373 // Remember collisions from last tick for fancy collision based actions
295 // (like a BSCharacter walking up stairs). 374 // (like a BSCharacter walking up stairs).
296 protected CollisionEventUpdate CollisionsLastTick; 375 public CollisionEventUpdate CollisionsLastTick;
297 376
298 // The simulation step is telling this object about a collision. 377 // The simulation step is telling this object about a collision.
299 // Return 'true' if a collision was processed and should be sent up. 378 // Return 'true' if a collision was processed and should be sent up.
@@ -424,104 +503,6 @@ public abstract class BSPhysObject : PhysicsActor
424 503
425 public BSActorCollection PhysicalActors; 504 public BSActorCollection PhysicalActors;
426 505
427 // There are some actions that must be performed for a physical object before each simulation step.
428 // These actions are optional so, rather than scanning all the physical objects and asking them
429 // if they have anything to do, a physical object registers for an event call before the step is performed.
430 // This bookkeeping makes it easy to add, remove and clean up after all these registrations.
431 private Dictionary<string, BSScene.PreStepAction> RegisteredPrestepActions = new Dictionary<string, BSScene.PreStepAction>();
432 private Dictionary<string, BSScene.PostStepAction> RegisteredPoststepActions = new Dictionary<string, BSScene.PostStepAction>();
433 protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn)
434 {
435 string identifier = op + "-" + id.ToString();
436
437 lock (RegisteredPrestepActions)
438 {
439 // Clean out any existing action
440 UnRegisterPreStepAction(op, id);
441 RegisteredPrestepActions[identifier] = actn;
442 PhysicsScene.BeforeStep += actn;
443 }
444 DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
445 }
446
447 // Unregister a pre step action. Safe to call if the action has not been registered.
448 // Returns 'true' if an action was actually removed
449 protected bool UnRegisterPreStepAction(string op, uint id)
450 {
451 string identifier = op + "-" + id.ToString();
452 bool removed = false;
453 lock (RegisteredPrestepActions)
454 {
455 if (RegisteredPrestepActions.ContainsKey(identifier))
456 {
457 PhysicsScene.BeforeStep -= RegisteredPrestepActions[identifier];
458 RegisteredPrestepActions.Remove(identifier);
459 removed = true;
460 }
461 }
462 DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
463 return removed;
464 }
465
466 protected void UnRegisterAllPreStepActions()
467 {
468 lock (RegisteredPrestepActions)
469 {
470 foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredPrestepActions)
471 {
472 PhysicsScene.BeforeStep -= kvp.Value;
473 }
474 RegisteredPrestepActions.Clear();
475 }
476 DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
477 }
478
479 protected void RegisterPostStepAction(string op, uint id, BSScene.PostStepAction actn)
480 {
481 string identifier = op + "-" + id.ToString();
482
483 lock (RegisteredPoststepActions)
484 {
485 // Clean out any existing action
486 UnRegisterPostStepAction(op, id);
487 RegisteredPoststepActions[identifier] = actn;
488 PhysicsScene.AfterStep += actn;
489 }
490 DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier);
491 }
492
493 // Unregister a pre step action. Safe to call if the action has not been registered.
494 // Returns 'true' if an action was actually removed.
495 protected bool UnRegisterPostStepAction(string op, uint id)
496 {
497 string identifier = op + "-" + id.ToString();
498 bool removed = false;
499 lock (RegisteredPoststepActions)
500 {
501 if (RegisteredPoststepActions.ContainsKey(identifier))
502 {
503 PhysicsScene.AfterStep -= RegisteredPoststepActions[identifier];
504 RegisteredPoststepActions.Remove(identifier);
505 removed = true;
506 }
507 }
508 DetailLog("{0},BSPhysObject.UnRegisterPostStepAction,id={1},removed={2}", LocalID, identifier, removed);
509 return removed;
510 }
511
512 protected void UnRegisterAllPostStepActions()
513 {
514 lock (RegisteredPoststepActions)
515 {
516 foreach (KeyValuePair<string, BSScene.PostStepAction> kvp in RegisteredPoststepActions)
517 {
518 PhysicsScene.AfterStep -= kvp.Value;
519 }
520 RegisteredPoststepActions.Clear();
521 }
522 DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID);
523 }
524
525 // When an update to the physical properties happens, this event is fired to let 506 // When an update to the physical properties happens, this event is fired to let
526 // different actors to modify the update before it is passed around 507 // different actors to modify the update before it is passed around
527 public delegate void PreUpdatePropertyAction(ref EntityProperties entprop); 508 public delegate void PreUpdatePropertyAction(ref EntityProperties entprop);
@@ -533,46 +514,6 @@ public abstract class BSPhysObject : PhysicsActor
533 actions(ref entprop); 514 actions(ref entprop);
534 } 515 }
535 516
536 private Dictionary<string, PreUpdatePropertyAction> RegisteredPreUpdatePropertyActions = new Dictionary<string, PreUpdatePropertyAction>();
537 public void RegisterPreUpdatePropertyAction(string identifier, PreUpdatePropertyAction actn)
538 {
539 lock (RegisteredPreUpdatePropertyActions)
540 {
541 // Clean out any existing action
542 UnRegisterPreUpdatePropertyAction(identifier);
543 RegisteredPreUpdatePropertyActions[identifier] = actn;
544 OnPreUpdateProperty += actn;
545 }
546 DetailLog("{0},BSPhysObject.RegisterPreUpdatePropertyAction,id={1}", LocalID, identifier);
547 }
548 public bool UnRegisterPreUpdatePropertyAction(string identifier)
549 {
550 bool removed = false;
551 lock (RegisteredPreUpdatePropertyActions)
552 {
553 if (RegisteredPreUpdatePropertyActions.ContainsKey(identifier))
554 {
555 OnPreUpdateProperty -= RegisteredPreUpdatePropertyActions[identifier];
556 RegisteredPreUpdatePropertyActions.Remove(identifier);
557 removed = true;
558 }
559 }
560 DetailLog("{0},BSPhysObject.UnRegisterPreUpdatePropertyAction,id={1},removed={2}", LocalID, identifier, removed);
561 return removed;
562 }
563 public void UnRegisterAllPreUpdatePropertyActions()
564 {
565 lock (RegisteredPreUpdatePropertyActions)
566 {
567 foreach (KeyValuePair<string, PreUpdatePropertyAction> kvp in RegisteredPreUpdatePropertyActions)
568 {
569 OnPreUpdateProperty -= kvp.Value;
570 }
571 RegisteredPreUpdatePropertyActions.Clear();
572 }
573 DetailLog("{0},BSPhysObject.UnRegisterAllPreUpdatePropertyAction,", LocalID);
574 }
575
576 #endregion // Per Simulation Step actions 517 #endregion // Per Simulation Step actions
577 518
578 // High performance detailed logging routine used by the physical objects. 519 // High performance detailed logging routine used by the physical objects.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index e56276a..3423d2e 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -55,9 +55,6 @@ public class BSPrim : BSPhysObject
55 private OMV.Vector3 _position; 55 private OMV.Vector3 _position;
56 56
57 private float _mass; // the mass of this object 57 private float _mass; // the mass of this object
58 private OMV.Vector3 _force;
59 private OMV.Vector3 _velocity;
60 private OMV.Vector3 _torque;
61 private OMV.Vector3 _acceleration; 58 private OMV.Vector3 _acceleration;
62 private OMV.Quaternion _orientation; 59 private OMV.Quaternion _orientation;
63 private int _physicsActorType; 60 private int _physicsActorType;
@@ -73,16 +70,13 @@ public class BSPrim : BSPhysObject
73 private int CrossingFailures { get; set; } 70 private int CrossingFailures { get; set; }
74 71
75 public BSDynamics VehicleActor; 72 public BSDynamics VehicleActor;
76 public string VehicleActorName = "BasicVehicle"; 73 public const string VehicleActorName = "BasicVehicle";
77 74
78 private BSVMotor _targetMotor; 75 public const string HoverActorName = "HoverActor";
79 private OMV.Vector3 _PIDTarget; 76 public const String LockedAxisActorName = "BSPrim.LockedAxis";
80 private float _PIDTau; 77 public const string MoveToTargetActorName = "MoveToTargetActor";
81 78 public const string SetForceActorName = "SetForceActor";
82 private BSFMotor _hoverMotor; 79 public const string SetTorqueActorName = "SetTorqueActor";
83 private float _PIDHoverHeight;
84 private PIDHoverType _PIDHoverType;
85 private float _PIDHoverTau;
86 80
87 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, 81 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
88 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 82 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
@@ -95,12 +89,13 @@ public class BSPrim : BSPhysObject
95 Scale = size; // prims are the size the user wants them to be (different for BSCharactes). 89 Scale = size; // prims are the size the user wants them to be (different for BSCharactes).
96 _orientation = rotation; 90 _orientation = rotation;
97 _buoyancy = 0f; 91 _buoyancy = 0f;
98 _velocity = OMV.Vector3.Zero; 92 RawVelocity = OMV.Vector3.Zero;
99 _rotationalVelocity = OMV.Vector3.Zero; 93 _rotationalVelocity = OMV.Vector3.Zero;
100 BaseShape = pbs; 94 BaseShape = pbs;
101 _isPhysical = pisPhysical; 95 _isPhysical = pisPhysical;
102 _isVolumeDetect = false; 96 _isVolumeDetect = false;
103 97
98 // We keep a handle to the vehicle actor so we can set vehicle parameters later.
104 VehicleActor = new BSDynamics(PhysicsScene, this, VehicleActorName); 99 VehicleActor = new BSDynamics(PhysicsScene, this, VehicleActorName);
105 PhysicalActors.Add(VehicleActorName, VehicleActor); 100 PhysicalActors.Add(VehicleActorName, VehicleActor);
106 101
@@ -233,7 +228,7 @@ public class BSPrim : BSPhysObject
233 // Called at taint time! 228 // Called at taint time!
234 public override void ZeroMotion(bool inTaintTime) 229 public override void ZeroMotion(bool inTaintTime)
235 { 230 {
236 _velocity = OMV.Vector3.Zero; 231 RawVelocity = OMV.Vector3.Zero;
237 _acceleration = OMV.Vector3.Zero; 232 _acceleration = OMV.Vector3.Zero;
238 _rotationalVelocity = OMV.Vector3.Zero; 233 _rotationalVelocity = OMV.Vector3.Zero;
239 234
@@ -270,19 +265,17 @@ public class BSPrim : BSPhysObject
270 if (axis.Z != 1) locking.Z = 0f; 265 if (axis.Z != 1) locking.Z = 0f;
271 LockedAxis = locking; 266 LockedAxis = locking;
272 267
273 if (LockedAxis != LockedAxisFree) 268 EnableActor(LockedAxis != LockedAxisFree, LockedAxisActorName, delegate()
274 { 269 {
275 PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate() 270 return new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName);
276 { 271 });
277 // If there is not already an axis locker, make one 272
278 if (!PhysicalActors.HasActor(LockedAxisActorName)) 273 // Update parameters so the new actor's Refresh() action is called at the right time.
279 { 274 PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate()
280 DetailLog("{0},BSPrim.LockAngularMotion,taint,registeringLockAxisActor", LocalID); 275 {
281 PhysicalActors.Add(LockedAxisActorName, new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName)); 276 UpdatePhysicalParameters();
282 } 277 });
283 UpdatePhysicalParameters(); 278
284 });
285 }
286 return; 279 return;
287 } 280 }
288 281
@@ -407,9 +400,9 @@ public class BSPrim : BSPhysObject
407 ZeroMotion(inTaintTime); 400 ZeroMotion(inTaintTime);
408 ret = true; 401 ret = true;
409 } 402 }
410 if (_velocity.LengthSquared() > BSParam.MaxLinearVelocity) 403 if (RawVelocity.LengthSquared() > BSParam.MaxLinearVelocity)
411 { 404 {
412 _velocity = Util.ClampV(_velocity, BSParam.MaxLinearVelocity); 405 RawVelocity = Util.ClampV(RawVelocity, BSParam.MaxLinearVelocity);
413 ret = true; 406 ret = true;
414 } 407 }
415 if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared) 408 if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared)
@@ -506,48 +499,25 @@ public class BSPrim : BSPhysObject
506 } 499 }
507 500
508 public override OMV.Vector3 Force { 501 public override OMV.Vector3 Force {
509 get { return _force; } 502 get { return RawForce; }
510 set { 503 set {
511 _force = value; 504 RawForce = value;
512 if (_force != OMV.Vector3.Zero) 505 EnableActor(RawForce != OMV.Vector3.Zero, SetForceActorName, delegate()
513 { 506 {
514 // If the force is non-zero, it must be reapplied each tick because 507 return new BSActorSetForce(PhysicsScene, this, SetForceActorName);
515 // Bullet clears the forces applied last frame. 508 });
516 RegisterPreStepAction("BSPrim.setForce", LocalID,
517 delegate(float timeStep)
518 {
519 if (!IsPhysicallyActive || _force == OMV.Vector3.Zero)
520 {
521 UnRegisterPreStepAction("BSPrim.setForce", LocalID);
522 return;
523 }
524
525 DetailLog("{0},BSPrim.setForce,preStep,force={1}", LocalID, _force);
526 if (PhysBody.HasPhysicalBody)
527 {
528 PhysicsScene.PE.ApplyCentralForce(PhysBody, _force);
529 ActivateIfPhysical(false);
530 }
531 }
532 );
533 }
534 else
535 {
536 UnRegisterPreStepAction("BSPrim.setForce", LocalID);
537 }
538 } 509 }
539 } 510 }
540 511
541 public override int VehicleType { 512 public override int VehicleType {
542 get { 513 get {
543 return (int)VehicleActor.Type; // if we are a vehicle, return that type 514 return (int)VehicleActor.Type;
544 } 515 }
545 set { 516 set {
546 Vehicle type = (Vehicle)value; 517 Vehicle type = (Vehicle)value;
547 518
548 PhysicsScene.TaintedObject("setVehicleType", delegate() 519 PhysicsScene.TaintedObject("setVehicleType", delegate()
549 { 520 {
550 // Done at taint time so we're sure the physics engine is not using the variables
551 // Vehicle code changes the parameters for this vehicle type. 521 // Vehicle code changes the parameters for this vehicle type.
552 VehicleActor.ProcessTypeChange(type); 522 VehicleActor.ProcessTypeChange(type);
553 ActivateIfPhysical(false); 523 ActivateIfPhysical(false);
@@ -670,63 +640,40 @@ public class BSPrim : BSPhysObject
670 } 640 }
671 } 641 }
672 } 642 }
673 public override OMV.Vector3 RawVelocity
674 {
675 get { return _velocity; }
676 set { _velocity = value; }
677 }
678 public override OMV.Vector3 Velocity { 643 public override OMV.Vector3 Velocity {
679 get { return _velocity; } 644 get { return RawVelocity; }
680 set { 645 set {
681 _velocity = value; 646 RawVelocity = value;
682 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() 647 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
683 { 648 {
684 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 649 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity);
685 ForceVelocity = _velocity; 650 ForceVelocity = RawVelocity;
686 }); 651 });
687 } 652 }
688 } 653 }
689 public override OMV.Vector3 ForceVelocity { 654 public override OMV.Vector3 ForceVelocity {
690 get { return _velocity; } 655 get { return RawVelocity; }
691 set { 656 set {
692 PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity"); 657 PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity");
693 658
694 _velocity = Util.ClampV(value, BSParam.MaxLinearVelocity); 659 RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity);
695 if (PhysBody.HasPhysicalBody) 660 if (PhysBody.HasPhysicalBody)
696 { 661 {
697 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, _velocity); 662 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, RawVelocity);
698 PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); 663 PhysicsScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
699 ActivateIfPhysical(false); 664 ActivateIfPhysical(false);
700 } 665 }
701 } 666 }
702 } 667 }
703 public override OMV.Vector3 Torque { 668 public override OMV.Vector3 Torque {
704 get { return _torque; } 669 get { return RawTorque; }
705 set { 670 set {
706 _torque = value; 671 RawTorque = value;
707 if (_torque != OMV.Vector3.Zero) 672 EnableActor(RawTorque != OMV.Vector3.Zero, SetTorqueActorName, delegate()
708 {
709 // If the torque is non-zero, it must be reapplied each tick because
710 // Bullet clears the forces applied last frame.
711 RegisterPreStepAction("BSPrim.setTorque", LocalID,
712 delegate(float timeStep)
713 {
714 if (!IsPhysicallyActive || _torque == OMV.Vector3.Zero)
715 {
716 UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
717 return;
718 }
719
720 if (PhysBody.HasPhysicalBody)
721 AddAngularForce(_torque, false, true);
722 }
723 );
724 }
725 else
726 { 673 {
727 UnRegisterPreStepAction("BSPrim.setTorque", LocalID); 674 return new BSActorSetTorque(PhysicsScene, this, SetTorqueActorName);
728 } 675 });
729 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 676 DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, RawTorque);
730 } 677 }
731 } 678 }
732 public override OMV.Vector3 Acceleration { 679 public override OMV.Vector3 Acceleration {
@@ -839,7 +786,6 @@ public class BSPrim : BSPhysObject
839 MakeDynamic(IsStatic); 786 MakeDynamic(IsStatic);
840 787
841 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) 788 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
842 VehicleActor.Refresh();
843 PhysicalActors.Refresh(); 789 PhysicalActors.Refresh();
844 790
845 // Arrange for collision events if the simulator wants them 791 // Arrange for collision events if the simulator wants them
@@ -909,7 +855,7 @@ public class BSPrim : BSPhysObject
909 855
910 // For good measure, make sure the transform is set through to the motion state 856 // For good measure, make sure the transform is set through to the motion state
911 ForcePosition = _position; 857 ForcePosition = _position;
912 ForceVelocity = _velocity; 858 ForceVelocity = RawVelocity;
913 ForceRotationalVelocity = _rotationalVelocity; 859 ForceRotationalVelocity = _rotationalVelocity;
914 860
915 // A dynamic object has mass 861 // A dynamic object has mass
@@ -966,15 +912,6 @@ public class BSPrim : BSPhysObject
966 } 912 }
967 } 913 }
968 914
969 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
970 // they need waking up when parameters are changed.
971 // Called in taint-time!!
972 private void ActivateIfPhysical(bool forceIt)
973 {
974 if (IsPhysical && PhysBody.HasPhysicalBody)
975 PhysicsScene.PE.Activate(PhysBody, forceIt);
976 }
977
978 // Turn on or off the flag controlling whether collision events are returned to the simulator. 915 // Turn on or off the flag controlling whether collision events are returned to the simulator.
979 private void EnableCollisions(bool wantsCollisionEvents) 916 private void EnableCollisions(bool wantsCollisionEvents)
980 { 917 {
@@ -1096,78 +1033,13 @@ public class BSPrim : BSPhysObject
1096 } 1033 }
1097 } 1034 }
1098 1035
1099 // Used for MoveTo
1100 public override OMV.Vector3 PIDTarget {
1101 set
1102 {
1103 // TODO: add a sanity check -- don't move more than a region or something like that.
1104 _PIDTarget = value;
1105 }
1106 }
1107 public override float PIDTau {
1108 set { _PIDTau = value; }
1109 }
1110 public override bool PIDActive { 1036 public override bool PIDActive {
1111 set { 1037 set {
1112 if (value) 1038 base.MoveToTargetActive = value;
1039 EnableActor(MoveToTargetActive, MoveToTargetActorName, delegate()
1113 { 1040 {
1114 // We're taking over after this. 1041 return new BSActorMoveToTarget(PhysicsScene, this, MoveToTargetActorName);
1115 ZeroMotion(true); 1042 });
1116
1117 _targetMotor = new BSVMotor("BSPrim.PIDTarget",
1118 _PIDTau, // timeScale
1119 BSMotor.Infinite, // decay time scale
1120 BSMotor.InfiniteVector, // friction timescale
1121 1f // efficiency
1122 );
1123 _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1124 _targetMotor.SetTarget(_PIDTarget);
1125 _targetMotor.SetCurrent(RawPosition);
1126 /*
1127 _targetMotor = new BSPIDVMotor("BSPrim.PIDTarget");
1128 _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1129
1130 _targetMotor.SetTarget(_PIDTarget);
1131 _targetMotor.SetCurrent(RawPosition);
1132 _targetMotor.TimeScale = _PIDTau;
1133 _targetMotor.Efficiency = 1f;
1134 */
1135
1136 RegisterPreStepAction("BSPrim.PIDTarget", LocalID, delegate(float timeStep)
1137 {
1138 if (!IsPhysicallyActive)
1139 {
1140 UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID);
1141 return;
1142 }
1143
1144 OMV.Vector3 origPosition = RawPosition; // DEBUG DEBUG (for printout below)
1145
1146 // 'movePosition' is where we'd like the prim to be at this moment.
1147 OMV.Vector3 movePosition = RawPosition + _targetMotor.Step(timeStep);
1148
1149 // If we are very close to our target, turn off the movement motor.
1150 if (_targetMotor.ErrorIsZero())
1151 {
1152 DetailLog("{0},BSPrim.PIDTarget,zeroMovement,movePos={1},pos={2},mass={3}",
1153 LocalID, movePosition, RawPosition, Mass);
1154 ForcePosition = _targetMotor.TargetValue;
1155 _targetMotor.Enabled = false;
1156 }
1157 else
1158 {
1159 _position = movePosition;
1160 PositionSanityCheck(true /* intaintTime */);
1161 ForcePosition = _position;
1162 }
1163 DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", LocalID, origPosition, movePosition);
1164 });
1165 }
1166 else
1167 {
1168 // Stop any targetting
1169 UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID);
1170 }
1171 } 1043 }
1172 } 1044 }
1173 1045
@@ -1175,88 +1047,14 @@ public class BSPrim : BSPhysObject
1175 // Hover Height will override MoveTo target's Z 1047 // Hover Height will override MoveTo target's Z
1176 public override bool PIDHoverActive { 1048 public override bool PIDHoverActive {
1177 set { 1049 set {
1178 if (value) 1050 base.HoverActive = value;
1051 EnableActor(HoverActive, HoverActorName, delegate()
1179 { 1052 {
1180 // Turning the target on 1053 return new BSActorHover(PhysicsScene, this, HoverActorName);
1181 _hoverMotor = new BSFMotor("BSPrim.Hover", 1054 });
1182 _PIDHoverTau, // timeScale
1183 BSMotor.Infinite, // decay time scale
1184 BSMotor.Infinite, // friction timescale
1185 1f // efficiency
1186 );
1187 _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight());
1188 _hoverMotor.SetCurrent(RawPosition.Z);
1189 _hoverMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1190
1191 RegisterPreStepAction("BSPrim.Hover", LocalID, delegate(float timeStep)
1192 {
1193 // Don't do hovering while the object is selected.
1194 if (!IsPhysicallyActive)
1195 return;
1196
1197 _hoverMotor.SetCurrent(RawPosition.Z);
1198 _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight());
1199 float targetHeight = _hoverMotor.Step(timeStep);
1200
1201 // 'targetHeight' is where we'd like the Z of the prim to be at this moment.
1202 // Compute the amount of force to push us there.
1203 float moveForce = (targetHeight - RawPosition.Z) * Mass;
1204 // Undo anything the object thinks it's doing at the moment
1205 moveForce = -RawVelocity.Z * Mass;
1206
1207 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, new OMV.Vector3(0f, 0f, moveForce));
1208 DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}", LocalID, targetHeight, moveForce, Mass);
1209 });
1210 }
1211 else
1212 {
1213 UnRegisterPreStepAction("BSPrim.Hover", LocalID);
1214 }
1215 }
1216 }
1217 public override float PIDHoverHeight {
1218 set { _PIDHoverHeight = value; }
1219 }
1220 public override PIDHoverType PIDHoverType {
1221 set { _PIDHoverType = value; }
1222 }
1223 public override float PIDHoverTau {
1224 set { _PIDHoverTau = value; }
1225 }
1226 // Based on current position, determine what we should be hovering at now.
1227 // Must recompute often. What if we walked offa cliff>
1228 private float ComputeCurrentPIDHoverHeight()
1229 {
1230 float ret = _PIDHoverHeight;
1231 float groundHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
1232
1233 switch (_PIDHoverType)
1234 {
1235 case PIDHoverType.Ground:
1236 ret = groundHeight + _PIDHoverHeight;
1237 break;
1238 case PIDHoverType.GroundAndWater:
1239 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition);
1240 if (groundHeight > waterHeight)
1241 {
1242 ret = groundHeight + _PIDHoverHeight;
1243 }
1244 else
1245 {
1246 ret = waterHeight + _PIDHoverHeight;
1247 }
1248 break;
1249 } 1055 }
1250 return ret;
1251 } 1056 }
1252 1057
1253
1254 // For RotLookAt
1255 public override OMV.Quaternion APIDTarget { set { return; } }
1256 public override bool APIDActive { set { return; } }
1257 public override float APIDStrength { set { return; } }
1258 public override float APIDDamping { set { return; } }
1259
1260 public override void AddForce(OMV.Vector3 force, bool pushforce) { 1058 public override void AddForce(OMV.Vector3 force, bool pushforce) {
1261 // Per documentation, max force is limited. 1059 // Per documentation, max force is limited.
1262 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); 1060 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
@@ -1324,10 +1122,8 @@ public class BSPrim : BSPhysObject
1324 } 1122 }
1325 } 1123 }
1326 1124
1327 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 1125 // BSPhysObject.AddAngularForce()
1328 AddAngularForce(force, pushforce, false); 1126 public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
1329 }
1330 public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
1331 { 1127 {
1332 if (force.IsFinite()) 1128 if (force.IsFinite())
1333 { 1129 {
@@ -1661,7 +1457,7 @@ public class BSPrim : BSPhysObject
1661 { 1457 {
1662 // Create the correct physical representation for this type of object. 1458 // Create the correct physical representation for this type of object.
1663 // Updates base.PhysBody and base.PhysShape with the new information. 1459 // Updates base.PhysBody and base.PhysShape with the new information.
1664 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. 1460 // Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary.
1665 PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody) 1461 PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody)
1666 { 1462 {
1667 // Called if the current prim body is about to be destroyed. 1463 // Called if the current prim body is about to be destroyed.
@@ -1675,9 +1471,9 @@ public class BSPrim : BSPhysObject
1675 return; 1471 return;
1676 } 1472 }
1677 1473
1474 // Called at taint-time
1678 protected virtual void RemoveBodyDependencies() 1475 protected virtual void RemoveBodyDependencies()
1679 { 1476 {
1680 VehicleActor.RemoveBodyDependencies();
1681 PhysicalActors.RemoveBodyDependencies(); 1477 PhysicalActors.RemoveBodyDependencies();
1682 } 1478 }
1683 1479
@@ -1685,6 +1481,7 @@ public class BSPrim : BSPhysObject
1685 // the world that things have changed. 1481 // the world that things have changed.
1686 public override void UpdateProperties(EntityProperties entprop) 1482 public override void UpdateProperties(EntityProperties entprop)
1687 { 1483 {
1484 // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator.
1688 TriggerPreUpdatePropertyAction(ref entprop); 1485 TriggerPreUpdatePropertyAction(ref entprop);
1689 1486
1690 // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG 1487 // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG
@@ -1694,8 +1491,8 @@ public class BSPrim : BSPhysObject
1694 _orientation = entprop.Rotation; 1491 _orientation = entprop.Rotation;
1695 // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be 1492 // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be
1696 // very sensitive to velocity changes. 1493 // very sensitive to velocity changes.
1697 if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(_velocity, BSParam.UpdateVelocityChangeThreshold)) 1494 if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(RawVelocity, BSParam.UpdateVelocityChangeThreshold))
1698 _velocity = entprop.Velocity; 1495 RawVelocity = entprop.Velocity;
1699 _acceleration = entprop.Acceleration; 1496 _acceleration = entprop.Acceleration;
1700 _rotationalVelocity = entprop.RotationalVelocity; 1497 _rotationalVelocity = entprop.RotationalVelocity;
1701 1498
@@ -1705,7 +1502,7 @@ public class BSPrim : BSPhysObject
1705 if (PositionSanityCheck(true /* inTaintTime */ )) 1502 if (PositionSanityCheck(true /* inTaintTime */ ))
1706 { 1503 {
1707 entprop.Position = _position; 1504 entprop.Position = _position;
1708 entprop.Velocity = _velocity; 1505 entprop.Velocity = RawVelocity;
1709 entprop.RotationalVelocity = _rotationalVelocity; 1506 entprop.RotationalVelocity = _rotationalVelocity;
1710 entprop.Acceleration = _acceleration; 1507 entprop.Acceleration = _acceleration;
1711 } 1508 }
@@ -1717,16 +1514,8 @@ public class BSPrim : BSPhysObject
1717 LastEntityProperties = CurrentEntityProperties; 1514 LastEntityProperties = CurrentEntityProperties;
1718 CurrentEntityProperties = entprop; 1515 CurrentEntityProperties = entprop;
1719 1516
1517 // Note that BSPrim can be overloaded by BSPrimLinkable which controls updates from root and children prims.
1720 base.RequestPhysicsterseUpdate(); 1518 base.RequestPhysicsterseUpdate();
1721 /*
1722 else
1723 {
1724 // For debugging, report the movement of children
1725 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1726 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1727 entprop.Acceleration, entprop.RotationalVelocity);
1728 }
1729 */
1730 } 1519 }
1731} 1520}
1732} 1521}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
index d65d407..28242d4 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
@@ -163,6 +163,15 @@ public class BSPrimLinkable : BSPrimDisplaced
163 // TODO: this will have to change when linksets are articulated. 163 // TODO: this will have to change when linksets are articulated.
164 base.UpdateProperties(entprop); 164 base.UpdateProperties(entprop);
165 } 165 }
166 /*
167 else
168 {
169 // For debugging, report the movement of children
170 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
171 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
172 entprop.Acceleration, entprop.RotationalVelocity);
173 }
174 */
166 // The linkset might like to know about changing locations 175 // The linkset might like to know about changing locations
167 Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); 176 Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
168 } 177 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 9818b05..8e05b58 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -316,6 +316,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
316 break; 316 break;
317 case "bulletxna": 317 case "bulletxna":
318 ret = new BSAPIXNA(engineName, this); 318 ret = new BSAPIXNA(engineName, this);
319 BSParam.ShouldUseBulletHACD = false;
319 break; 320 break;
320 } 321 }
321 322
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 220fbbc..76860e4 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -722,7 +722,7 @@ public sealed class BSShapeCollection : IDisposable
722 // Remove usage of the previous shape. 722 // Remove usage of the previous shape.
723 DereferenceShape(prim.PhysShape, shapeCallback); 723 DereferenceShape(prim.PhysShape, shapeCallback);
724 724
725 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); 725 newShape = CreatePhysicalHull(prim, newHullKey, prim.BaseShape, prim.Size, lod);
726 // It might not have been created if we're waiting for an asset. 726 // It might not have been created if we're waiting for an asset.
727 newShape = VerifyMeshCreated(newShape, prim); 727 newShape = VerifyMeshCreated(newShape, prim);
728 728
@@ -733,7 +733,7 @@ public sealed class BSShapeCollection : IDisposable
733 } 733 }
734 734
735 List<ConvexResult> m_hulls; 735 List<ConvexResult> m_hulls;
736 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 736 private BulletShape CreatePhysicalHull(BSPhysObject prim, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
737 { 737 {
738 738
739 BulletShape newShape = new BulletShape(); 739 BulletShape newShape = new BulletShape();
@@ -747,116 +747,153 @@ public sealed class BSShapeCollection : IDisposable
747 } 747 }
748 else 748 else
749 { 749 {
750 // Build a new hull in the physical world. 750 if (BSParam.ShouldUseBulletHACD)
751 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
752 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false);
753 if (meshData != null)
754 { 751 {
755 752 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID);
756 int[] indices = meshData.getIndexListAsInt(); 753 MeshDesc meshDesc;
757 List<OMV.Vector3> vertices = meshData.getVertexList(); 754 if (!Meshes.TryGetValue(newHullKey, out meshDesc))
758
759 //format conversion from IMesh format to DecompDesc format
760 List<int> convIndices = new List<int>();
761 List<float3> convVertices = new List<float3>();
762 for (int ii = 0; ii < indices.GetLength(0); ii++)
763 { 755 {
764 convIndices.Add(indices[ii]); 756 // That's odd because the mesh should have been created before the hull
757 // but, since it doesn't exist, create it.
758 newShape = CreatePhysicalMesh(prim, newHullKey, prim.BaseShape, prim.Size, lod);
759 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,noMeshBuiltNew,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
760
761 if (newShape.HasPhysicalShape)
762 {
763 ReferenceShape(newShape);
764 Meshes.TryGetValue(newHullKey, out meshDesc);
765 }
765 } 766 }
766 foreach (OMV.Vector3 vv in vertices) 767 if (meshDesc.shape.HasPhysicalShape)
767 { 768 {
768 convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); 769 HACDParams parms;
770 parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
771 parms.minClusters = BSParam.BHullMinClusters;
772 parms.compacityWeight = BSParam.BHullCompacityWeight;
773 parms.volumeWeight = BSParam.BHullVolumeWeight;
774 parms.concavity = BSParam.BHullConcavity;
775 parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
776 parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
777 parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
778 parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
779
780 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
781 newShape = PhysicsScene.PE.BuildHullShapeFromMesh(PhysicsScene.World, meshDesc.shape, parms);
782 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
769 } 783 }
770 784 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
771 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit; 785 }
772 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes) 786 if (!newShape.HasPhysicalShape)
787 {
788 // Build a new hull in the physical world.
789 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
790 IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */, false, false);
791 if (meshData != null)
773 { 792 {
774 // Simple primitive shapes we know are convex so they are better implemented with 793 int[] indices = meshData.getIndexListAsInt();
775 // fewer hulls. 794 List<OMV.Vector3> vertices = meshData.getVertexList();
776 // Check for simple shape (prim without cuts) and reduce split parameter if so. 795
777 if (PrimHasNoCuts(pbs)) 796 //format conversion from IMesh format to DecompDesc format
797 List<int> convIndices = new List<int>();
798 List<float3> convVertices = new List<float3>();
799 for (int ii = 0; ii < indices.GetLength(0); ii++)
778 { 800 {
779 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes; 801 convIndices.Add(indices[ii]);
802 }
803 foreach (OMV.Vector3 vv in vertices)
804 {
805 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
780 } 806 }
781 }
782 807
783 // setup and do convex hull conversion 808 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
784 m_hulls = new List<ConvexResult>(); 809 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
785 DecompDesc dcomp = new DecompDesc(); 810 {
786 dcomp.mIndices = convIndices; 811 // Simple primitive shapes we know are convex so they are better implemented with
787 dcomp.mVertices = convVertices; 812 // fewer hulls.
788 dcomp.mDepth = maxDepthSplit; 813 // Check for simple shape (prim without cuts) and reduce split parameter if so.
789 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent; 814 if (PrimHasNoCuts(pbs))
790 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent; 815 {
791 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices; 816 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
792 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth; 817 }
793 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); 818 }
794 // create the hull into the _hulls variable
795 convexBuilder.process(dcomp);
796
797 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
798 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
799
800 // Convert the vertices and indices for passing to unmanaged.
801 // The hull information is passed as a large floating point array.
802 // The format is:
803 // convHulls[0] = number of hulls
804 // convHulls[1] = number of vertices in first hull
805 // convHulls[2] = hull centroid X coordinate
806 // convHulls[3] = hull centroid Y coordinate
807 // convHulls[4] = hull centroid Z coordinate
808 // convHulls[5] = first hull vertex X
809 // convHulls[6] = first hull vertex Y
810 // convHulls[7] = first hull vertex Z
811 // convHulls[8] = second hull vertex X
812 // ...
813 // convHulls[n] = number of vertices in second hull
814 // convHulls[n+1] = second hull centroid X coordinate
815 // ...
816 //
817 // TODO: is is very inefficient. Someday change the convex hull generator to return
818 // data structures that do not need to be converted in order to pass to Bullet.
819 // And maybe put the values directly into pinned memory rather than marshaling.
820 int hullCount = m_hulls.Count;
821 int totalVertices = 1; // include one for the count of the hulls
822 foreach (ConvexResult cr in m_hulls)
823 {
824 totalVertices += 4; // add four for the vertex count and centroid
825 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
826 }
827 float[] convHulls = new float[totalVertices];
828 819
829 convHulls[0] = (float)hullCount; 820 // setup and do convex hull conversion
830 int jj = 1; 821 m_hulls = new List<ConvexResult>();
831 foreach (ConvexResult cr in m_hulls) 822 DecompDesc dcomp = new DecompDesc();
832 { 823 dcomp.mIndices = convIndices;
833 // copy vertices for index access 824 dcomp.mVertices = convVertices;
834 float3[] verts = new float3[cr.HullVertices.Count]; 825 dcomp.mDepth = maxDepthSplit;
835 int kk = 0; 826 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
836 foreach (float3 ff in cr.HullVertices) 827 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
828 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
829 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
830 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
831 // create the hull into the _hulls variable
832 convexBuilder.process(dcomp);
833
834 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
835 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
836
837 // Convert the vertices and indices for passing to unmanaged.
838 // The hull information is passed as a large floating point array.
839 // The format is:
840 // convHulls[0] = number of hulls
841 // convHulls[1] = number of vertices in first hull
842 // convHulls[2] = hull centroid X coordinate
843 // convHulls[3] = hull centroid Y coordinate
844 // convHulls[4] = hull centroid Z coordinate
845 // convHulls[5] = first hull vertex X
846 // convHulls[6] = first hull vertex Y
847 // convHulls[7] = first hull vertex Z
848 // convHulls[8] = second hull vertex X
849 // ...
850 // convHulls[n] = number of vertices in second hull
851 // convHulls[n+1] = second hull centroid X coordinate
852 // ...
853 //
854 // TODO: is is very inefficient. Someday change the convex hull generator to return
855 // data structures that do not need to be converted in order to pass to Bullet.
856 // And maybe put the values directly into pinned memory rather than marshaling.
857 int hullCount = m_hulls.Count;
858 int totalVertices = 1; // include one for the count of the hulls
859 foreach (ConvexResult cr in m_hulls)
837 { 860 {
838 verts[kk++] = ff; 861 totalVertices += 4; // add four for the vertex count and centroid
862 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
839 } 863 }
864 float[] convHulls = new float[totalVertices];
840 865
841 // add to the array one hull's worth of data 866 convHulls[0] = (float)hullCount;
842 convHulls[jj++] = cr.HullIndices.Count; 867 int jj = 1;
843 convHulls[jj++] = 0f; // centroid x,y,z 868 foreach (ConvexResult cr in m_hulls)
844 convHulls[jj++] = 0f;
845 convHulls[jj++] = 0f;
846 foreach (int ind in cr.HullIndices)
847 { 869 {
848 convHulls[jj++] = verts[ind].x; 870 // copy vertices for index access
849 convHulls[jj++] = verts[ind].y; 871 float3[] verts = new float3[cr.HullVertices.Count];
850 convHulls[jj++] = verts[ind].z; 872 int kk = 0;
873 foreach (float3 ff in cr.HullVertices)
874 {
875 verts[kk++] = ff;
876 }
877
878 // add to the array one hull's worth of data
879 convHulls[jj++] = cr.HullIndices.Count;
880 convHulls[jj++] = 0f; // centroid x,y,z
881 convHulls[jj++] = 0f;
882 convHulls[jj++] = 0f;
883 foreach (int ind in cr.HullIndices)
884 {
885 convHulls[jj++] = verts[ind].x;
886 convHulls[jj++] = verts[ind].y;
887 convHulls[jj++] = verts[ind].z;
888 }
851 } 889 }
890 // create the hull data structure in Bullet
891 newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
852 } 892 }
853 // create the hull data structure in Bullet
854 newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
855 } 893 }
894 newShape.shapeKey = newHullKey;
856 } 895 }
857 896
858 newShape.shapeKey = newHullKey;
859
860 return newShape; 897 return newShape;
861 } 898 }
862 899
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index cd15850..5240ad8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -213,13 +213,13 @@ public sealed class BSTerrainManager : IDisposable
213 }); 213 });
214 } 214 }
215 215
216 // Another region is calling this region passing a terrain. 216 // Another region is calling this region and passing a terrain.
217 // A region that is not the mega-region root will pass its terrain to the root region so the root region 217 // A region that is not the mega-region root will pass its terrain to the root region so the root region
218 // physics engine will have all the terrains. 218 // physics engine will have all the terrains.
219 private void AddMegaRegionChildTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) 219 private void AddMegaRegionChildTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
220 { 220 {
221 // Since we are called by another region's thread, the action must be rescheduled onto our processing thread. 221 // Since we are called by another region's thread, the action must be rescheduled onto our processing thread.
222 PhysicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + m_worldOffset.ToString(), 0, delegate() 222 PhysicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + minCoords.ToString(), id, delegate()
223 { 223 {
224 UpdateTerrain(id, heightMap, minCoords, maxCoords); 224 UpdateTerrain(id, heightMap, minCoords, maxCoords);
225 }); 225 });
@@ -306,7 +306,7 @@ public sealed class BSTerrainManager : IDisposable
306 newTerrainID = ++m_terrainCount; 306 newTerrainID = ++m_terrainCount;
307 307
308 DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}", 308 DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}",
309 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); 309 BSScene.DetailLogZero, newTerrainID, minCoords, maxCoords);
310 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); 310 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
311 m_terrains.Add(terrainRegionBase, newTerrainPhys); 311 m_terrains.Add(terrainRegionBase, newTerrainPhys);
312 312
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index 8a15abe..a0131c7 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -6,7 +6,6 @@ Enable vehicle border crossings (at least as poorly as ODE)
6 Terrain skirts 6 Terrain skirts
7 Avatar created in previous region and not new region when crossing border 7 Avatar created in previous region and not new region when crossing border
8 Vehicle recreated in new sim at small Z value (offset from root value?) (DONE) 8 Vehicle recreated in new sim at small Z value (offset from root value?) (DONE)
9Lock axis
10Deleting a linkset while standing on the root will leave the physical shape of the root behind. 9Deleting a linkset while standing on the root will leave the physical shape of the root behind.
11 Not sure if it is because standing on it. Done with large prim linksets. 10 Not sure if it is because standing on it. Done with large prim linksets.
12Linkset child rotations. 11Linkset child rotations.
@@ -344,3 +343,5 @@ Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
344 Verify that angular motion specified around Z moves in the vehicle coordinates. 343 Verify that angular motion specified around Z moves in the vehicle coordinates.
345 DONE 20130120: BulletSim properly applies force in vehicle relative coordinates. 344 DONE 20130120: BulletSim properly applies force in vehicle relative coordinates.
346Nebadon vehicles turning funny in arena (DONE) 345Nebadon vehicles turning funny in arena (DONE)
346Lock axis (DONE 20130401)
347
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
index b4abc1d..4bf2a82 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
@@ -27,6 +27,8 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
30using OpenMetaverse; 32using OpenMetaverse;
31using OpenSim.Framework; 33using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
@@ -34,10 +36,10 @@ using OpenSim.Region.CoreModules.World.Land;
34 36
35namespace OpenSim.Region.RegionCombinerModule 37namespace OpenSim.Region.RegionCombinerModule
36{ 38{
37public class RegionCombinerLargeLandChannel : ILandChannel 39 public class RegionCombinerLargeLandChannel : ILandChannel
38 { 40 {
39 // private static readonly ILog m_log = 41// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42
41 private RegionData RegData; 43 private RegionData RegData;
42 private ILandChannel RootRegionLandChannel; 44 private ILandChannel RootRegionLandChannel;
43 private readonly List<RegionData> RegionConnections; 45 private readonly List<RegionData> RegionConnections;
@@ -75,40 +77,51 @@ public class RegionCombinerLargeLandChannel : ILandChannel
75 77
76 public ILandObject GetLandObject(int x, int y) 78 public ILandObject GetLandObject(int x, int y)
77 { 79 {
78 //m_log.DebugFormat("[BIGLANDTESTINT]: <{0},{1}>", x, y); 80 return GetLandObject((float)x, (float)y);
79 81
80 if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize) 82// m_log.DebugFormat("[BIGLANDTESTINT]: <{0},{1}>", x, y);
81 { 83//
82 return RootRegionLandChannel.GetLandObject(x, y); 84// if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
83 } 85// {
84 else 86// return RootRegionLandChannel.GetLandObject(x, y);
85 { 87// }
86 int offsetX = (x / (int)Constants.RegionSize); 88// else
87 int offsetY = (y / (int)Constants.RegionSize); 89// {
88 offsetX *= (int)Constants.RegionSize; 90// int offsetX = (x / (int)Constants.RegionSize);
89 offsetY *= (int)Constants.RegionSize; 91// int offsetY = (y / (int)Constants.RegionSize);
90 92// offsetX *= (int)Constants.RegionSize;
91 foreach (RegionData regionData in RegionConnections) 93// offsetY *= (int)Constants.RegionSize;
92 { 94//
93 if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY) 95// foreach (RegionData regionData in RegionConnections)
94 { 96// {
95 return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY); 97// if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY)
96 } 98// {
97 } 99// m_log.DebugFormat(
98 ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene); 100// "[REGION COMBINER LARGE LAND CHANNEL]: Found region {0} at offset {1},{2}",
99 obj.LandData.Name = "NO LAND"; 101// regionData.RegionScene.Name, offsetX, offsetY);
100 return obj; 102//
101 } 103// return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY);
104// }
105// }
106// //ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
107// //obj.LandData.Name = "NO LAND";
108// //return obj;
109// }
110//
111// m_log.DebugFormat("[REGION COMBINER LARGE LAND CHANNEL]: No region found at {0},{1}, returning null", x, y);
112//
113// return null;
102 } 114 }
103 115
104 public ILandObject GetLandObject(int localID) 116 public ILandObject GetLandObject(int localID)
105 { 117 {
118 // XXX: Possibly should be looking in every land channel, not just the root.
106 return RootRegionLandChannel.GetLandObject(localID); 119 return RootRegionLandChannel.GetLandObject(localID);
107 } 120 }
108 121
109 public ILandObject GetLandObject(float x, float y) 122 public ILandObject GetLandObject(float x, float y)
110 { 123 {
111 //m_log.DebugFormat("[BIGLANDTESTFLOAT]: <{0},{1}>", x, y); 124// m_log.DebugFormat("[BIGLANDTESTFLOAT]: <{0},{1}>", x, y);
112 125
113 if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize) 126 if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
114 { 127 {
@@ -125,14 +138,22 @@ public class RegionCombinerLargeLandChannel : ILandChannel
125 { 138 {
126 if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY) 139 if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY)
127 { 140 {
141// m_log.DebugFormat(
142// "[REGION COMBINER LARGE LAND CHANNEL]: Found region {0} at offset {1},{2}",
143// regionData.RegionScene.Name, offsetX, offsetY);
144
128 return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY); 145 return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY);
129 } 146 }
130 } 147 }
131 148
132 ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene); 149// ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
133 obj.LandData.Name = "NO LAND"; 150// obj.LandData.Name = "NO LAND";
134 return obj; 151// return obj;
135 } 152 }
153
154// m_log.DebugFormat("[REGION COMBINER LARGE LAND CHANNEL]: No region found at {0},{1}, returning null", x, y);
155
156 return null;
136 } 157 }
137 158
138 public bool IsForcefulBansAllowed() 159 public bool IsForcefulBansAllowed()
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 26850c4..fa238aa 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -528,8 +528,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
528 { 528 {
529 File.Delete(savedState); 529 File.Delete(savedState);
530 } 530 }
531 catch(Exception) 531 catch (Exception e)
532 { 532 {
533 m_log.Warn(
534 string.Format(
535 "[SCRIPT INSTANCE]: Could not delete script state {0} for script {1} (id {2}) in part {3} (id {4}) in object {5} in {6}. Exception ",
536 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name),
537 e);
533 } 538 }
534 } 539 }
535 540