aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
authorMelanie2012-07-28 00:39:36 +0100
committerMelanie2012-07-28 00:39:36 +0100
commit771d79e83e9ef5686aee5fe1c572673cff291083 (patch)
treeb37749fc1929ffd6dd1b9c2c4e29120accf26b99 /OpenSim/Region/Physics
parentMerge branch 'master' into careminster (diff)
parentLSL/OSSL lacks Math.Min & Math.Max implementations. (diff)
downloadopensim-SC-771d79e83e9ef5686aee5fe1c572673cff291083.zip
opensim-SC-771d79e83e9ef5686aee5fe1c572673cff291083.tar.gz
opensim-SC-771d79e83e9ef5686aee5fe1c572673cff291083.tar.bz2
opensim-SC-771d79e83e9ef5686aee5fe1c572673cff291083.tar.xz
Merge branch 'master' into careminster
Conflicts: OpenSim/Framework/Monitoring/BaseStatsCollector.cs OpenSim/Region/Application/OpenSim.cs OpenSim/Region/Application/OpenSimBase.cs OpenSim/Region/Framework/Scenes/SceneManager.cs bin/OpenMetaverse.Rendering.Meshmerizer.dll bin/OpenMetaverse.StructuredData.dll bin/OpenMetaverse.dll bin/OpenMetaverseTypes.dll prebuild.xml
Diffstat (limited to 'OpenSim/Region/Physics')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs115
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs178
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs308
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs343
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs652
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs48
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs15
7 files changed, 1171 insertions, 488 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
new file mode 100755
index 0000000..fbb9e21
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -0,0 +1,115 @@
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 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public class BSConstraint : IDisposable
36{
37 private BulletSim m_world;
38 private BulletBody m_body1;
39 private BulletBody m_body2;
40 private BulletConstraint m_constraint;
41 private bool m_enabled = false;
42
43 public BSConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
44 Vector3 frame1, Quaternion frame1rot,
45 Vector3 frame2, Quaternion frame2rot
46 )
47 {
48 m_world = world;
49 m_body1 = obj1;
50 m_body2 = obj2;
51 m_constraint = new BulletConstraint(BulletSimAPI.CreateConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
52 frame1, frame1rot,
53 frame2, frame2rot));
54 m_enabled = true;
55 }
56
57 public void Dispose()
58 {
59 if (m_enabled)
60 {
61 // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
62 BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
63 m_enabled = false;
64 }
65 }
66
67 public BulletBody Body1 { get { return m_body1; } }
68 public BulletBody Body2 { get { return m_body2; } }
69
70 public bool SetLinearLimits(Vector3 low, Vector3 high)
71 {
72 bool ret = false;
73 if (m_enabled)
74 ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high);
75 return ret;
76 }
77
78 public bool SetAngularLimits(Vector3 low, Vector3 high)
79 {
80 bool ret = false;
81 if (m_enabled)
82 ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high);
83 return ret;
84 }
85
86 public bool UseFrameOffset(bool useOffset)
87 {
88 bool ret = false;
89 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
90 if (m_enabled)
91 ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff);
92 return ret;
93 }
94
95 public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce)
96 {
97 bool ret = false;
98 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
99 if (m_enabled)
100 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
101 return ret;
102 }
103
104 public bool CalculateTransforms()
105 {
106 bool ret = false;
107 if (m_enabled)
108 {
109 BulletSimAPI.CalculateTransforms2(m_constraint.Ptr);
110 ret = true;
111 }
112 return ret;
113 }
114}
115}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
new file mode 100755
index 0000000..a2650fb
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
@@ -0,0 +1,178 @@
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 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using log4net;
31using OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35
36public class BSConstraintCollection : IDisposable
37{
38 // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
39 // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]";
40
41 delegate bool ConstraintAction(BSConstraint constrain);
42
43 private List<BSConstraint> m_constraints;
44 private BulletSim m_world;
45
46 public BSConstraintCollection(BulletSim world)
47 {
48 m_world = world;
49 m_constraints = new List<BSConstraint>();
50 }
51
52 public void Dispose()
53 {
54 this.Clear();
55 }
56
57 public void Clear()
58 {
59 foreach (BSConstraint cons in m_constraints)
60 {
61 cons.Dispose();
62 }
63 m_constraints.Clear();
64 }
65
66 public BSConstraint CreateConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
67 Vector3 frame1, Quaternion frame1rot,
68 Vector3 frame2, Quaternion frame2rot)
69 {
70 BSConstraint constrain = new BSConstraint(world, obj1, obj2, frame1, frame1rot, frame2, frame2rot);
71
72 this.AddConstraint(constrain);
73 return constrain;
74 }
75
76 public bool AddConstraint(BSConstraint cons)
77 {
78 // There is only one constraint between any bodies. Remove any old just to make sure.
79 RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
80
81 m_constraints.Add(cons);
82
83 return true;
84 }
85
86 // Get the constraint between two bodies. There can be only one the way we're using them.
87 public bool TryGetConstraint(BulletBody body1, BulletBody body2, out BSConstraint returnConstraint)
88 {
89 bool found = false;
90 BSConstraint foundConstraint = null;
91
92 uint lookingID1 = body1.ID;
93 uint lookingID2 = body2.ID;
94 ForEachConstraint(delegate(BSConstraint constrain)
95 {
96 if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2)
97 || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
98 {
99 foundConstraint = constrain;
100 found = true;
101 }
102 return found;
103 });
104 returnConstraint = foundConstraint;
105 return found;
106 }
107
108 public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2)
109 {
110 // return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID);
111
112 bool ret = false;
113 BSConstraint constrain;
114
115 if (this.TryGetConstraint(body1, body2, out constrain))
116 {
117 // remove the constraint from our collection
118 m_constraints.Remove(constrain);
119 // tell the engine that all its structures need to be freed
120 constrain.Dispose();
121 // we destroyed something
122 ret = true;
123 }
124
125 return ret;
126 }
127
128 public bool RemoveAndDestroyConstraint(BulletBody body1)
129 {
130 // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID);
131
132 List<BSConstraint> toRemove = new List<BSConstraint>();
133 uint lookingID = body1.ID;
134 ForEachConstraint(delegate(BSConstraint constrain)
135 {
136 if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
137 {
138 toRemove.Add(constrain);
139 }
140 return false;
141 });
142 lock (m_constraints)
143 {
144 foreach (BSConstraint constrain in toRemove)
145 {
146 m_constraints.Remove(constrain);
147 constrain.Dispose();
148 }
149 }
150 return (toRemove.Count > 0);
151 }
152
153 public bool RecalculateAllConstraints()
154 {
155 foreach (BSConstraint constrain in m_constraints)
156 {
157 constrain.CalculateTransforms();
158 }
159 return true;
160 }
161
162 // Lock the constraint list and loop through it.
163 // The constraint action returns 'true' if it wants the loop aborted.
164 private void ForEachConstraint(ConstraintAction action)
165 {
166 lock (m_constraints)
167 {
168 foreach (BSConstraint constrain in m_constraints)
169 {
170 if (action(constrain))
171 break;
172 }
173 }
174 }
175
176
177}
178}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
new file mode 100755
index 0000000..3bc2100
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -0,0 +1,308 @@
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 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OMV = OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35public class BSLinkset
36{
37 private static string LogHeader = "[BULLETSIM LINKSET]";
38
39 private BSPrim m_linksetRoot;
40 public BSPrim Root { get { return m_linksetRoot; } }
41
42 private BSScene m_scene;
43
44 private List<BSPrim> m_children;
45
46 // We lock the diddling of linkset classes to prevent any badness.
47 // This locks the modification of the instances of this class. Changes
48 // to the physical representation is done via the tainting mechenism.
49 private object m_linksetActivityLock = new Object();
50
51 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
52 private float m_mass;
53 public float LinksetMass
54 {
55 get
56 {
57 m_mass = ComputeLinksetMass();
58 return m_mass;
59 }
60 }
61
62 public OMV.Vector3 CenterOfMass
63 {
64 get { return ComputeLinksetCenterOfMass(); }
65 }
66
67 public OMV.Vector3 GeometricCenter
68 {
69 get { return ComputeLinksetGeometricCenter(); }
70 }
71
72 public BSLinkset(BSScene scene, BSPrim parent)
73 {
74 // A simple linkset of one (no children)
75 m_scene = scene;
76 m_linksetRoot = parent;
77 m_children = new List<BSPrim>();
78 m_mass = parent.MassRaw;
79 }
80
81 // Link to a linkset where the child knows the parent.
82 // Parent changing should not happen so do some sanity checking.
83 // We return the parent's linkset so the child can track it's membership.
84 public BSLinkset AddMeToLinkset(BSPrim child, BSPrim parent)
85 {
86 lock (m_linksetActivityLock)
87 {
88 parent.Linkset.AddChildToLinkset(child);
89 }
90 return parent.Linkset;
91 }
92
93 public BSLinkset RemoveMeFromLinkset(BSPrim child)
94 {
95 lock (m_linksetActivityLock)
96 {
97 if (IsRoot(child))
98 {
99 // if root of linkset, take the linkset apart
100 while (m_children.Count > 0)
101 {
102 // Note that we don't do a foreach because the remove routine
103 // takes it out of the list.
104 RemoveChildFromLinkset(m_children[0]);
105 }
106 m_children.Clear(); // just to make sure
107 }
108 else
109 {
110 // Just removing a child from an existing linkset
111 RemoveChildFromLinkset(child);
112 }
113 }
114
115 // The child is down to a linkset of just itself
116 return new BSLinkset(m_scene, child);
117 }
118
119 // An existing linkset had one of its members rebuilt or something.
120 // Undo all the physical linking and rebuild the physical linkset.
121 public bool RefreshLinkset(BSPrim requestor)
122 {
123 return true;
124 }
125
126
127 // Return 'true' if the passed object is the root object of this linkset
128 public bool IsRoot(BSPrim requestor)
129 {
130 return (requestor.LocalID == m_linksetRoot.LocalID);
131 }
132
133 // Return 'true' if this linkset has any children (more than the root member)
134 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
135
136 // Return 'true' if this child is in this linkset
137 public bool HasChild(BSPrim child)
138 {
139 bool ret = false;
140 foreach (BSPrim bp in m_children)
141 {
142 if (child.LocalID == bp.LocalID)
143 {
144 ret = true;
145 break;
146 }
147 }
148 return ret;
149 }
150
151 private float ComputeLinksetMass()
152 {
153 float mass = m_linksetRoot.MassRaw;
154 foreach (BSPrim bp in m_children)
155 {
156 mass += bp.MassRaw;
157 }
158 return mass;
159 }
160
161 private OMV.Vector3 ComputeLinksetCenterOfMass()
162 {
163 OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw;
164 float totalMass = m_linksetRoot.MassRaw;
165
166 foreach (BSPrim bp in m_children)
167 {
168 com += bp.Position * bp.MassRaw;
169 totalMass += bp.MassRaw;
170 }
171 com /= totalMass;
172
173 return com;
174 }
175
176 private OMV.Vector3 ComputeLinksetGeometricCenter()
177 {
178 OMV.Vector3 com = m_linksetRoot.Position;
179
180 foreach (BSPrim bp in m_children)
181 {
182 com += bp.Position * bp.MassRaw;
183 }
184 com /= m_children.Count + 1;
185
186 return com;
187 }
188
189 // I am the root of a linkset and a new child is being added
190 public void AddChildToLinkset(BSPrim pchild)
191 {
192 BSPrim child = pchild;
193 if (!HasChild(child))
194 {
195 m_children.Add(child);
196
197 m_scene.TaintedObject(delegate()
198 {
199 DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID);
200 DetailLog("{0},AddChildToLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID);
201 PhysicallyLinkAChildToRoot(pchild); // build the physical binding between me and the child
202 });
203 }
204 return;
205 }
206
207 // I am the root of a linkset and one of my children is being removed.
208 // Safe to call even if the child is not really in my linkset.
209 public void RemoveChildFromLinkset(BSPrim pchild)
210 {
211 BSPrim child = pchild;
212
213 if (m_children.Remove(child))
214 {
215 m_scene.TaintedObject(delegate()
216 {
217 DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
218 DetailLog("{0},RemoveChildFromLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID);
219
220 if (m_children.Count == 0)
221 {
222 // if the linkset is empty, make sure all linkages have been removed
223 PhysicallyUnlinkAllChildrenFromRoot();
224 }
225 else
226 {
227 PhysicallyUnlinkAChildFromRoot(pchild);
228 }
229 });
230 }
231 else
232 {
233 // This will happen if we remove the root of the linkset first. Non-fatal occurance.
234 // m_scene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
235 }
236 return;
237 }
238
239 // Create a constraint between me (root of linkset) and the passed prim (the child).
240 // Called at taint time!
241 private void PhysicallyLinkAChildToRoot(BSPrim childPrim)
242 {
243 // Zero motion for children so they don't interpolate
244 childPrim.ZeroMotion();
245
246 // relative position normalized to the root prim
247 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(m_linksetRoot.Orientation);
248 OMV.Vector3 childRelativePosition = (childPrim.Position - m_linksetRoot.Position) * invThisOrientation;
249
250 // relative rotation of the child to the parent
251 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
252
253 // create a constraint that allows no freedom of movement between the two objects
254 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
255 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
256 DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID);
257 BSConstraint constrain = m_scene.Constraints.CreateConstraint(
258 m_scene.World, m_linksetRoot.Body, childPrim.Body,
259 childRelativePosition,
260 childRelativeRotation,
261 OMV.Vector3.Zero,
262 OMV.Quaternion.Identity);
263 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
264 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
265
266 // tweek the constraint to increase stability
267 constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset));
268 constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor),
269 m_scene.Params.linkConstraintTransMotorMaxVel,
270 m_scene.Params.linkConstraintTransMotorMaxForce);
271
272 }
273
274 // Remove linkage between myself and a particular child
275 // Called at taint time!
276 private void PhysicallyUnlinkAChildFromRoot(BSPrim childPrim)
277 {
278 DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
279 LogHeader, m_linksetRoot.LocalID, childPrim.LocalID);
280 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID);
281 // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID);
282 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body, childPrim.Body);
283 }
284
285 // Remove linkage between myself and any possible children I might have
286 // Called at taint time!
287 private void PhysicallyUnlinkAllChildrenFromRoot()
288 {
289 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
290 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", m_linksetRoot.LocalID);
291 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body);
292 // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID);
293 }
294
295 // Invoke the detailed logger and output something if it's enabled.
296 private void DebugLog(string msg, params Object[] args)
297 {
298 m_scene.Logger.DebugFormat(msg, args);
299 }
300
301 // Invoke the detailed logger and output something if it's enabled.
302 private void DetailLog(string msg, params Object[] args)
303 {
304 m_scene.PhysicsLogging.Write(msg, args);
305 }
306
307}
308}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index a19d6d7..7590d93 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -66,7 +66,7 @@ public sealed class BSPrim : PhysicsActor
66 private bool _isSelected; 66 private bool _isSelected;
67 private bool _isVolumeDetect; 67 private bool _isVolumeDetect;
68 private OMV.Vector3 _position; 68 private OMV.Vector3 _position;
69 private float _mass; 69 private float _mass; // the mass of this object
70 private float _density; 70 private float _density;
71 private OMV.Vector3 _force; 71 private OMV.Vector3 _force;
72 private OMV.Vector3 _velocity; 72 private OMV.Vector3 _velocity;
@@ -89,14 +89,22 @@ public sealed class BSPrim : PhysicsActor
89 private bool _kinematic; 89 private bool _kinematic;
90 private float _buoyancy; 90 private float _buoyancy;
91 91
92 private BSPrim _parentPrim; 92 // Membership in a linkset is controlled by this class.
93 private List<BSPrim> _childrenPrims; 93 private BSLinkset _linkset;
94 public BSLinkset Linkset
95 {
96 get { return _linkset; }
97 set { _linkset = value; }
98 }
94 99
95 private int _subscribedEventsMs = 0; 100 private int _subscribedEventsMs = 0;
96 private int _nextCollisionOkTime = 0; 101 private int _nextCollisionOkTime = 0;
97 long _collidingStep; 102 long _collidingStep;
98 long _collidingGroundStep; 103 long _collidingGroundStep;
99 104
105 private BulletBody m_body;
106 public BulletBody Body { get { return m_body; } }
107
100 private BSDynamics _vehicle; 108 private BSDynamics _vehicle;
101 109
102 private OMV.Vector3 _PIDTarget; 110 private OMV.Vector3 _PIDTarget;
@@ -130,14 +138,18 @@ public sealed class BSPrim : PhysicsActor
130 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 138 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material
131 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 139 _density = _scene.Params.defaultDensity; // TODO: compute based on object material
132 _restitution = _scene.Params.defaultRestitution; 140 _restitution = _scene.Params.defaultRestitution;
133 _parentPrim = null; // not a child or a parent 141 _linkset = new BSLinkset(_scene, this); // a linkset of one
134 _vehicle = new BSDynamics(this); // add vehicleness 142 _vehicle = new BSDynamics(this); // add vehicleness
135 _childrenPrims = new List<BSPrim>();
136 _mass = CalculateMass(); 143 _mass = CalculateMass();
137 // do the actual object creation at taint time 144 // do the actual object creation at taint time
138 _scene.TaintedObject(delegate() 145 _scene.TaintedObject(delegate()
139 { 146 {
140 RecreateGeomAndObject(); 147 RecreateGeomAndObject();
148
149 // Get the pointer to the physical body for this object.
150 // At the moment, we're still letting BulletSim manage the creation and destruction
151 // of the object. Someday we'll move that into the C# code.
152 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
141 }); 153 });
142 } 154 }
143 155
@@ -153,16 +165,8 @@ public sealed class BSPrim : PhysicsActor
153 165
154 _scene.TaintedObject(delegate() 166 _scene.TaintedObject(delegate()
155 { 167 {
156 // undo any dependance with/on other objects 168 // Undo any links between me and any other object
157 if (_parentPrim != null) 169 _linkset = _linkset.RemoveMeFromLinkset(this);
158 {
159 // If I'm someone's child, tell them to forget about me.
160 _parentPrim.RemoveChildFromLinkset(this);
161 _parentPrim = null;
162 }
163
164 // make sure there are no possible children depending on me
165 UnlinkAllChildren();
166 170
167 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. 171 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
168 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); 172 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID);
@@ -179,7 +183,7 @@ public sealed class BSPrim : PhysicsActor
179 _scene.TaintedObject(delegate() 183 _scene.TaintedObject(delegate()
180 { 184 {
181 _mass = CalculateMass(); // changing size changes the mass 185 _mass = CalculateMass(); // changing size changes the mass
182 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, Mass, IsPhysical); 186 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical);
183 RecreateGeomAndObject(); 187 RecreateGeomAndObject();
184 }); 188 });
185 } 189 }
@@ -218,32 +222,8 @@ public sealed class BSPrim : PhysicsActor
218 BSPrim parent = obj as BSPrim; 222 BSPrim parent = obj as BSPrim;
219 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); 223 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID);
220 DetailLog("{0},link,parent={1}", LocalID, obj.LocalID); 224 DetailLog("{0},link,parent={1}", LocalID, obj.LocalID);
221 // TODO: decide if this parent checking needs to happen at taint time 225
222 if (_parentPrim == null) 226 _linkset = _linkset.AddMeToLinkset(this, parent);
223 {
224 if (parent != null)
225 {
226 // I don't have a parent so I am joining a linkset
227 parent.AddChildToLinkset(this);
228 }
229 }
230 else
231 {
232 // I already have a parent, is parenting changing?
233 if (parent != _parentPrim)
234 {
235 if (parent == null)
236 {
237 // we are being removed from a linkset
238 _parentPrim.RemoveChildFromLinkset(this);
239 }
240 else
241 {
242 // asking to reparent a prim should not happen
243 m_log.ErrorFormat("{0}: link(): Reparenting a prim. ", LogHeader);
244 }
245 }
246 }
247 return; 227 return;
248 } 228 }
249 229
@@ -252,92 +232,28 @@ public sealed class BSPrim : PhysicsActor
252 // TODO: decide if this parent checking needs to happen at taint time 232 // TODO: decide if this parent checking needs to happen at taint time
253 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 233 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
254 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, 234 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
255 (_parentPrim==null ? "NULL" : _parentPrim._avName+"/"+_parentPrim.LocalID.ToString())); 235 _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString());
256 DetailLog("{0},delink,parent={1}", LocalID, (_parentPrim==null ? "NULL" : _parentPrim.LocalID.ToString())); 236 DetailLog("{0},delink,parent={1}", LocalID, _linkset.Root.LocalID.ToString());
257 if (_parentPrim != null)
258 {
259 _parentPrim.RemoveChildFromLinkset(this);
260 }
261 return;
262 }
263
264 // I am the root of a linkset and a new child is being added
265 public void AddChildToLinkset(BSPrim pchild)
266 {
267 BSPrim child = pchild;
268 _scene.TaintedObject(delegate()
269 {
270 if (!_childrenPrims.Contains(child))
271 {
272 DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, this.LocalID);
273 DetailLog("{0},AddChildToLinkset,child={1}", LocalID, pchild.LocalID);
274 _childrenPrims.Add(child);
275 child._parentPrim = this; // the child has gained a parent
276 // RecreateGeomAndObject(); // rebuild my shape with the new child added
277 LinkAChildToMe(pchild); // build the physical binding between me and the child
278
279 _mass = CalculateMass();
280 }
281 });
282 return;
283 }
284
285 // I am the root of a linkset and one of my children is being removed.
286 // Safe to call even if the child is not really in my linkset.
287 public void RemoveChildFromLinkset(BSPrim pchild)
288 {
289 BSPrim child = pchild;
290 _scene.TaintedObject(delegate()
291 {
292 if (_childrenPrims.Contains(child))
293 {
294 DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
295 DetailLog("{0},RemoveChildFromLinkset,child={1}", LocalID, pchild.LocalID);
296 _childrenPrims.Remove(child);
297 child._parentPrim = null; // the child has lost its parent
298 if (_childrenPrims.Count == 0)
299 {
300 // if the linkset is empty, make sure all linkages have been removed
301 UnlinkAllChildren();
302 }
303 else
304 {
305 // RecreateGeomAndObject(); // rebuild my shape with the child removed
306 UnlinkAChildFromMe(pchild);
307 }
308
309 _mass = CalculateMass();
310 }
311 else
312 {
313 m_log.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset");
314 }
315 });
316 return;
317 }
318 237
319 // return true if we are the root of a linkset (there are children to manage) 238 _linkset.RemoveMeFromLinkset(this);
320 public bool IsRootOfLinkset 239 return;
321 {
322 get { return (_parentPrim == null && _childrenPrims.Count != 0); }
323 } 240 }
324 241
325 // Set motion values to zero. 242 // Set motion values to zero.
326 // Do it to the properties so the values get set in the physics engine. 243 // Do it to the properties so the values get set in the physics engine.
327 // Push the setting of the values to the viewer. 244 // Push the setting of the values to the viewer.
328 // Called at taint time! 245 // Called at taint time!
329 private void ZeroMotion() 246 public void ZeroMotion()
330 { 247 {
331 _velocity = OMV.Vector3.Zero; 248 _velocity = OMV.Vector3.Zero;
332 _acceleration = OMV.Vector3.Zero; 249 _acceleration = OMV.Vector3.Zero;
333 _rotationalVelocity = OMV.Vector3.Zero; 250 _rotationalVelocity = OMV.Vector3.Zero;
334 251
335 // Zero some other properties directly into the physics engine 252 // Zero some other properties directly into the physics engine
336 IntPtr obj = BulletSimAPI.GetBodyHandleWorldID2(_scene.WorldID, LocalID); 253 BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero);
337 BulletSimAPI.SetVelocity2(obj, OMV.Vector3.Zero); 254 BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero);
338 BulletSimAPI.SetAngularVelocity2(obj, OMV.Vector3.Zero); 255 BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
339 BulletSimAPI.SetInterpolation2(obj, OMV.Vector3.Zero, OMV.Vector3.Zero); 256 BulletSimAPI.ClearForces2(Body.Ptr);
340 BulletSimAPI.ClearForces2(obj);
341 } 257 }
342 258
343 public override void LockAngularMotion(OMV.Vector3 axis) 259 public override void LockAngularMotion(OMV.Vector3 axis)
@@ -348,9 +264,10 @@ public sealed class BSPrim : PhysicsActor
348 264
349 public override OMV.Vector3 Position { 265 public override OMV.Vector3 Position {
350 get { 266 get {
351 // child prims move around based on their parent. Need to get the latest location 267 if (!_linkset.IsRoot(this))
352 if (_parentPrim != null) 268 // child prims move around based on their parent. Need to get the latest location
353 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 269 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
270
354 // don't do the GetObjectPosition for root elements because this function is called a zillion times 271 // don't do the GetObjectPosition for root elements because this function is called a zillion times
355 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 272 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
356 return _position; 273 return _position;
@@ -366,16 +283,31 @@ public sealed class BSPrim : PhysicsActor
366 } 283 }
367 } 284 }
368 285
369 // Return the effective mass of the object. Non-physical objects do not have mass. 286 // Return the effective mass of the object.
370 public override float Mass { 287 // If there are multiple items in the linkset, add them together for the root
371 get { 288 public override float Mass
372 if (IsPhysical) 289 {
373 return _mass; 290 get
374 else 291 {
375 return 0f; 292 return _linkset.LinksetMass;
376 } 293 }
377 } 294 }
378 295
296 // used when we only want this prim's mass and not the linkset thing
297 public float MassRaw { get { return _mass; } }
298
299 // Is this used?
300 public override OMV.Vector3 CenterOfMass
301 {
302 get { return _linkset.CenterOfMass; }
303 }
304
305 // Is this used?
306 public override OMV.Vector3 GeometricCenter
307 {
308 get { return _linkset.GeometricCenter; }
309 }
310
379 public override OMV.Vector3 Force { 311 public override OMV.Vector3 Force {
380 get { return _force; } 312 get { return _force; }
381 set { 313 set {
@@ -383,7 +315,8 @@ public sealed class BSPrim : PhysicsActor
383 _scene.TaintedObject(delegate() 315 _scene.TaintedObject(delegate()
384 { 316 {
385 DetailLog("{0},SetForce,taint,force={1}", LocalID, _force); 317 DetailLog("{0},SetForce,taint,force={1}", LocalID, _force);
386 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 318 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
319 BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
387 }); 320 });
388 } 321 }
389 } 322 }
@@ -407,8 +340,7 @@ public sealed class BSPrim : PhysicsActor
407 _scene.TaintedObject(delegate() 340 _scene.TaintedObject(delegate()
408 { 341 {
409 // Tell the physics engine to clear state 342 // Tell the physics engine to clear state
410 IntPtr obj = BulletSimAPI.GetBodyHandleWorldID2(_scene.WorldID, LocalID); 343 BulletSimAPI.ClearForces2(this.Body.Ptr);
411 BulletSimAPI.ClearForces2(obj);
412 }); 344 });
413 345
414 // make it so the scene will call us each tick to do vehicle things 346 // make it so the scene will call us each tick to do vehicle things
@@ -420,7 +352,6 @@ public sealed class BSPrim : PhysicsActor
420 } 352 }
421 public override void VehicleFloatParam(int param, float value) 353 public override void VehicleFloatParam(int param, float value)
422 { 354 {
423 m_log.DebugFormat("{0} VehicleFloatParam. {1} <= {2}", LogHeader, param, value);
424 _scene.TaintedObject(delegate() 355 _scene.TaintedObject(delegate()
425 { 356 {
426 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 357 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
@@ -428,7 +359,6 @@ public sealed class BSPrim : PhysicsActor
428 } 359 }
429 public override void VehicleVectorParam(int param, OMV.Vector3 value) 360 public override void VehicleVectorParam(int param, OMV.Vector3 value)
430 { 361 {
431 m_log.DebugFormat("{0} VehicleVectorParam. {1} <= {2}", LogHeader, param, value);
432 _scene.TaintedObject(delegate() 362 _scene.TaintedObject(delegate()
433 { 363 {
434 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 364 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
@@ -436,7 +366,6 @@ public sealed class BSPrim : PhysicsActor
436 } 366 }
437 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 367 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
438 { 368 {
439 m_log.DebugFormat("{0} VehicleRotationParam. {1} <= {2}", LogHeader, param, rotation);
440 _scene.TaintedObject(delegate() 369 _scene.TaintedObject(delegate()
441 { 370 {
442 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 371 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
@@ -444,7 +373,6 @@ public sealed class BSPrim : PhysicsActor
444 } 373 }
445 public override void VehicleFlags(int param, bool remove) 374 public override void VehicleFlags(int param, bool remove)
446 { 375 {
447 m_log.DebugFormat("{0} VehicleFlags. {1}. Remove={2}", LogHeader, param, remove);
448 _scene.TaintedObject(delegate() 376 _scene.TaintedObject(delegate()
449 { 377 {
450 _vehicle.ProcessVehicleFlags(param, remove); 378 _vehicle.ProcessVehicleFlags(param, remove);
@@ -470,8 +398,6 @@ public sealed class BSPrim : PhysicsActor
470 return; 398 return;
471 } 399 }
472 400
473 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
474 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
475 public override OMV.Vector3 Velocity { 401 public override OMV.Vector3 Velocity {
476 get { return _velocity; } 402 get { return _velocity; }
477 set { 403 set {
@@ -500,9 +426,9 @@ public sealed class BSPrim : PhysicsActor
500 } 426 }
501 public override OMV.Quaternion Orientation { 427 public override OMV.Quaternion Orientation {
502 get { 428 get {
503 if (_parentPrim != null) 429 if (!_linkset.IsRoot(this))
504 { 430 {
505 // children move around because tied to parent. Get a fresh value. 431 // Children move around because tied to parent. Get a fresh value.
506 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); 432 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
507 } 433 }
508 return _orientation; 434 return _orientation;
@@ -552,14 +478,16 @@ public sealed class BSPrim : PhysicsActor
552 private void SetObjectDynamic() 478 private void SetObjectDynamic()
553 { 479 {
554 // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid); 480 // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid);
555 // non-physical things work best with a mass of zero 481
556 if (!IsStatic) 482 RecreateGeomAndObject();
557 { 483
558 _mass = CalculateMass(); 484 float mass = _mass;
559 RecreateGeomAndObject(); 485 // Bullet wants static objects have a mass of zero
560 } 486 if (IsStatic)
561 DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, Mass); 487 mass = 0f;
562 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), Mass); 488
489 DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, mass);
490 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
563 } 491 }
564 492
565 // prims don't fly 493 // prims don't fly
@@ -1001,6 +929,9 @@ public sealed class BSPrim : PhysicsActor
1001 929
1002 returnMass = _density * volume; 930 returnMass = _density * volume;
1003 931
932 /*
933 * This change means each object keeps its own mass and the Mass property
934 * will return the sum if we're part of a linkset.
1004 if (IsRootOfLinkset) 935 if (IsRootOfLinkset)
1005 { 936 {
1006 foreach (BSPrim prim in _childrenPrims) 937 foreach (BSPrim prim in _childrenPrims)
@@ -1008,6 +939,7 @@ public sealed class BSPrim : PhysicsActor
1008 returnMass += prim.CalculateMass(); 939 returnMass += prim.CalculateMass();
1009 } 940 }
1010 } 941 }
942 */
1011 943
1012 if (returnMass <= 0) 944 if (returnMass <= 0)
1013 returnMass = 0.0001f; 945 returnMass = 0.0001f;
@@ -1023,9 +955,11 @@ public sealed class BSPrim : PhysicsActor
1023 // The objects needs a hull if it's physical otherwise a mesh is enough 955 // The objects needs a hull if it's physical otherwise a mesh is enough
1024 // No locking here because this is done when we know physics is not simulating 956 // No locking here because this is done when we know physics is not simulating
1025 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used 957 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used
1026 private void CreateGeom(bool forceRebuild) 958 // Returns 'true' if the geometry was rebuilt
959 private bool CreateGeom(bool forceRebuild)
1027 { 960 {
1028 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. 961 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
962 bool ret = false;
1029 if (!_scene.NeedsMeshing(_pbs)) 963 if (!_scene.NeedsMeshing(_pbs))
1030 { 964 {
1031 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 965 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
@@ -1033,18 +967,26 @@ public sealed class BSPrim : PhysicsActor
1033 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) 967 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
1034 { 968 {
1035 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 969 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
1036 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 970 if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)
1037 DetailLog("{0},CreateGeom,sphere", LocalID); 971 {
1038 // Bullet native objects are scaled by the Bullet engine so pass the size in 972 DetailLog("{0},CreateGeom,sphere", LocalID);
1039 _scale = _size; 973 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
974 ret = true;
975 // Bullet native objects are scaled by the Bullet engine so pass the size in
976 _scale = _size;
977 }
1040 } 978 }
1041 } 979 }
1042 else 980 else
1043 { 981 {
1044 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size); 982 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size);
1045 DetailLog("{0},CreateGeom,box", LocalID); 983 if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)
1046 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 984 {
1047 _scale = _size; 985 DetailLog("{0},CreateGeom,box", LocalID);
986 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
987 ret = true;
988 _scale = _size;
989 }
1048 } 990 }
1049 } 991 }
1050 else 992 else
@@ -1056,6 +998,7 @@ public sealed class BSPrim : PhysicsActor
1056 // physical objects require a hull for interaction. 998 // physical objects require a hull for interaction.
1057 // This will create the mesh if it doesn't already exist 999 // This will create the mesh if it doesn't already exist
1058 CreateGeomHull(); 1000 CreateGeomHull();
1001 ret = true;
1059 } 1002 }
1060 } 1003 }
1061 else 1004 else
@@ -1064,9 +1007,11 @@ public sealed class BSPrim : PhysicsActor
1064 { 1007 {
1065 // Static (non-physical) objects only need a mesh for bumping into 1008 // Static (non-physical) objects only need a mesh for bumping into
1066 CreateGeomMesh(); 1009 CreateGeomMesh();
1010 ret = true;
1067 } 1011 }
1068 } 1012 }
1069 } 1013 }
1014 return ret;
1070 } 1015 }
1071 1016
1072 // No locking here because this is done when we know physics is not simulating 1017 // No locking here because this is done when we know physics is not simulating
@@ -1251,20 +1196,18 @@ public sealed class BSPrim : PhysicsActor
1251 // No locking here because this is done when the physics engine is not simulating 1196 // No locking here because this is done when the physics engine is not simulating
1252 private void CreateObject() 1197 private void CreateObject()
1253 { 1198 {
1254 if (IsRootOfLinkset) 1199 // this routine is called when objects are rebuilt.
1255 { 1200
1256 // Create a linkset around this object 1201 // the mesh or hull must have already been created in Bullet
1257 CreateLinkset(); 1202 ShapeData shape;
1258 } 1203 FillShapeInfo(out shape);
1259 else 1204 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1260 { 1205 BulletSimAPI.CreateObject(_scene.WorldID, shape);
1261 // simple object 1206 // the CreateObject() may have recreated the rigid body. Make sure we have the latest.
1262 // the mesh or hull must have already been created in Bullet 1207 m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID);
1263 ShapeData shape; 1208
1264 FillShapeInfo(out shape); 1209 // The root object could have been recreated. Make sure everything linksety is up to date.
1265 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); 1210 _linkset.RefreshLinkset(this);
1266 BulletSimAPI.CreateObject(_scene.WorldID, shape);
1267 }
1268 } 1211 }
1269 1212
1270 // Copy prim's info into the BulletSim shape description structure 1213 // Copy prim's info into the BulletSim shape description structure
@@ -1276,7 +1219,7 @@ public sealed class BSPrim : PhysicsActor
1276 shape.Rotation = _orientation; 1219 shape.Rotation = _orientation;
1277 shape.Velocity = _velocity; 1220 shape.Velocity = _velocity;
1278 shape.Scale = _scale; 1221 shape.Scale = _scale;
1279 shape.Mass = Mass; 1222 shape.Mass = _isPhysical ? _mass : 0f;
1280 shape.Buoyancy = _buoyancy; 1223 shape.Buoyancy = _buoyancy;
1281 shape.HullKey = _hullKey; 1224 shape.HullKey = _hullKey;
1282 shape.MeshKey = _meshKey; 1225 shape.MeshKey = _meshKey;
@@ -1286,72 +1229,6 @@ public sealed class BSPrim : PhysicsActor
1286 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; 1229 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1287 } 1230 }
1288 1231
1289 #region Linkset creation and destruction
1290
1291 // Create the linkset by putting constraints between the objects of the set so they cannot move
1292 // relative to each other.
1293 void CreateLinkset()
1294 {
1295 DebugLog("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1);
1296
1297 // remove any constraints that might be in place
1298 DebugLog("{0}: CreateLinkset: RemoveConstraints between me and any children", LogHeader, LocalID);
1299 BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID);
1300
1301 // create constraints between the root prim and each of the children
1302 foreach (BSPrim prim in _childrenPrims)
1303 {
1304 LinkAChildToMe(prim);
1305 }
1306 }
1307
1308 // Create a constraint between me (root of linkset) and the passed prim (the child).
1309 // Called at taint time!
1310 private void LinkAChildToMe(BSPrim childPrim)
1311 {
1312 // Zero motion for children so they don't interpolate
1313 childPrim.ZeroMotion();
1314
1315 // relative position normalized to the root prim
1316 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(this._orientation);
1317 OMV.Vector3 childRelativePosition = (childPrim._position - this._position) * invThisOrientation;
1318
1319 // relative rotation of the child to the parent
1320 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim._orientation;
1321
1322 // create a constraint that allows no freedom of movement between the two objects
1323 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
1324 DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
1325 DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID);
1326 BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, childPrim.LocalID,
1327 childRelativePosition,
1328 childRelativeRotation,
1329 OMV.Vector3.Zero,
1330 OMV.Quaternion.Identity,
1331 OMV.Vector3.Zero, OMV.Vector3.Zero,
1332 OMV.Vector3.Zero, OMV.Vector3.Zero);
1333 }
1334
1335 // Remove linkage between myself and a particular child
1336 // Called at taint time!
1337 private void UnlinkAChildFromMe(BSPrim childPrim)
1338 {
1339 DebugLog("{0}: UnlinkAChildFromMe: RemoveConstraint between root prim {1} and child prim {2}",
1340 LogHeader, LocalID, childPrim.LocalID);
1341 DetailLog("{0},UnlinkAChildFromMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID);
1342 BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID);
1343 }
1344
1345 // Remove linkage between myself and any possible children I might have
1346 // Called at taint time!
1347 private void UnlinkAllChildren()
1348 {
1349 DebugLog("{0}: UnlinkAllChildren:", LogHeader);
1350 DetailLog("{0},UnlinkAllChildren,taint", LocalID);
1351 BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID);
1352 }
1353
1354 #endregion // Linkset creation and destruction
1355 1232
1356 // Rebuild the geometry and object. 1233 // Rebuild the geometry and object.
1357 // This is called when the shape changes so we need to recreate the mesh/hull. 1234 // This is called when the shape changes so we need to recreate the mesh/hull.
@@ -1429,7 +1306,7 @@ public sealed class BSPrim : PhysicsActor
1429 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. 1306 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
1430 1307
1431 // Updates only for individual prims and for the root object of a linkset. 1308 // Updates only for individual prims and for the root object of a linkset.
1432 if (_parentPrim == null) 1309 if (_linkset.IsRoot(this))
1433 { 1310 {
1434 // Assign to the local variables so the normal set action does not happen 1311 // Assign to the local variables so the normal set action does not happen
1435 _position = entprop.Position; 1312 _position = entprop.Position;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 7cc3fe3..c6d622b 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -73,7 +73,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
74 private static readonly string LogHeader = "[BULLETS SCENE]"; 74 private static readonly string LogHeader = "[BULLETS SCENE]";
75 75
76 private void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); } 76 public void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); }
77 77
78 public string BulletSimVersion = "?"; 78 public string BulletSimVersion = "?";
79 79
@@ -87,6 +87,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
87 private uint m_worldID; 87 private uint m_worldID;
88 public uint WorldID { get { return m_worldID; } } 88 public uint WorldID { get { return m_worldID; } }
89 89
90 // let my minuions use my logger
91 public ILog Logger { get { return m_log; } }
92
90 private bool m_initialized = false; 93 private bool m_initialized = false;
91 94
92 private int m_detailedStatsStep = 0; 95 private int m_detailedStatsStep = 0;
@@ -103,6 +106,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
103 get { return m_sculptLOD; } 106 get { return m_sculptLOD; }
104 } 107 }
105 108
109 private BulletSim m_worldSim;
110 public BulletSim World
111 {
112 get { return m_worldSim; }
113 }
114 private BSConstraintCollection m_constraintCollection;
115 public BSConstraintCollection Constraints
116 {
117 get { return m_constraintCollection; }
118 }
119
106 private int m_maxSubSteps; 120 private int m_maxSubSteps;
107 private float m_fixedTimeStep; 121 private float m_fixedTimeStep;
108 private long m_simulationStep = 0; 122 private long m_simulationStep = 0;
@@ -229,6 +243,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
229 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), 243 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
230 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); 244 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject());
231 245
246 // Initialization to support the transition to a new API which puts most of the logic
247 // into the C# code so it is easier to modify and add to.
248 m_worldSim = new BulletSim(m_worldID, BulletSimAPI.GetSimHandle2(m_worldID));
249 m_constraintCollection = new BSConstraintCollection(World);
250
232 m_initialized = true; 251 m_initialized = true;
233 } 252 }
234 253
@@ -237,116 +256,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
237 private void GetInitialParameterValues(IConfigSource config) 256 private void GetInitialParameterValues(IConfigSource config)
238 { 257 {
239 ConfigurationParameters parms = new ConfigurationParameters(); 258 ConfigurationParameters parms = new ConfigurationParameters();
259 m_params[0] = parms;
240 260
241 _meshSculptedPrim = true; // mesh sculpted prims 261 SetParameterDefaultValues();
242 _forceSimplePrimMeshing = false; // use complex meshing if called for
243
244 m_meshLOD = 8f;
245 m_sculptLOD = 32f;
246
247 shouldDebugLog = false;
248 m_detailedStatsStep = 0; // disabled
249
250 m_maxSubSteps = 10;
251 m_fixedTimeStep = 1f / 60f;
252 m_maxCollisionsPerFrame = 2048;
253 m_maxUpdatesPerFrame = 2048;
254 m_maximumObjectMass = 10000.01f;
255
256 PID_D = 2200f;
257 PID_P = 900f;
258
259 parms.defaultFriction = 0.5f;
260 parms.defaultDensity = 10.000006836f; // Aluminum g/cm3
261 parms.defaultRestitution = 0f;
262 parms.collisionMargin = 0.0f;
263 parms.gravity = -9.80665f;
264
265 parms.linearDamping = 0.0f;
266 parms.angularDamping = 0.0f;
267 parms.deactivationTime = 0.2f;
268 parms.linearSleepingThreshold = 0.8f;
269 parms.angularSleepingThreshold = 1.0f;
270 parms.ccdMotionThreshold = 0.0f; // set to zero to disable
271 parms.ccdSweptSphereRadius = 0.0f;
272 parms.contactProcessingThreshold = 0.1f;
273
274 parms.terrainFriction = 0.5f;
275 parms.terrainHitFraction = 0.8f;
276 parms.terrainRestitution = 0f;
277 parms.avatarFriction = 0.5f;
278 parms.avatarRestitution = 0.0f;
279 parms.avatarDensity = 60f;
280 parms.avatarCapsuleRadius = 0.37f;
281 parms.avatarCapsuleHeight = 1.5f; // 2.140599f
282 parms.avatarContactProcessingThreshold = 0.1f;
283
284 parms.maxPersistantManifoldPoolSize = 0f;
285 parms.shouldDisableContactPoolDynamicAllocation = ConfigurationParameters.numericTrue;
286 parms.shouldForceUpdateAllAabbs = ConfigurationParameters.numericFalse;
287 parms.shouldRandomizeSolverOrder = ConfigurationParameters.numericFalse;
288 parms.shouldSplitSimulationIslands = ConfigurationParameters.numericFalse;
289 parms.shouldEnableFrictionCaching = ConfigurationParameters.numericFalse;
290 parms.numberOfSolverIterations = 0f; // means use default
291 262
292 if (config != null) 263 if (config != null)
293 { 264 {
294 // If there are specifications in the ini file, use those values 265 // If there are specifications in the ini file, use those values
295 // WHEN ADDING OR UPDATING THIS SECTION, BE SURE TO UPDATE OpenSimDefaults.ini
296 // ALSO REMEMBER TO UPDATE THE RUNTIME SETTING OF THE PARAMETERS.
297 IConfig pConfig = config.Configs["BulletSim"]; 266 IConfig pConfig = config.Configs["BulletSim"];
298 if (pConfig != null) 267 if (pConfig != null)
299 { 268 {
300 _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); 269 SetParameterConfigurationValues(pConfig);
301 _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing);
302
303 shouldDebugLog = pConfig.GetBoolean("ShouldDebugLog", shouldDebugLog);
304 m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep);
305
306 m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD);
307 m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD);
308
309 m_maxSubSteps = pConfig.GetInt("MaxSubSteps", m_maxSubSteps);
310 m_fixedTimeStep = pConfig.GetFloat("FixedTimeStep", m_fixedTimeStep);
311 m_maxCollisionsPerFrame = pConfig.GetInt("MaxCollisionsPerFrame", m_maxCollisionsPerFrame);
312 m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame);
313 m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass);
314
315 PID_D = pConfig.GetFloat("PIDDerivative", PID_D);
316 PID_P = pConfig.GetFloat("PIDProportional", PID_P);
317
318 parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction);
319 parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity);
320 parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution);
321 parms.collisionMargin = pConfig.GetFloat("CollisionMargin", parms.collisionMargin);
322 parms.gravity = pConfig.GetFloat("Gravity", parms.gravity);
323
324 parms.linearDamping = pConfig.GetFloat("LinearDamping", parms.linearDamping);
325 parms.angularDamping = pConfig.GetFloat("AngularDamping", parms.angularDamping);
326 parms.deactivationTime = pConfig.GetFloat("DeactivationTime", parms.deactivationTime);
327 parms.linearSleepingThreshold = pConfig.GetFloat("LinearSleepingThreshold", parms.linearSleepingThreshold);
328 parms.angularSleepingThreshold = pConfig.GetFloat("AngularSleepingThreshold", parms.angularSleepingThreshold);
329 parms.ccdMotionThreshold = pConfig.GetFloat("CcdMotionThreshold", parms.ccdMotionThreshold);
330 parms.ccdSweptSphereRadius = pConfig.GetFloat("CcdSweptSphereRadius", parms.ccdSweptSphereRadius);
331 parms.contactProcessingThreshold = pConfig.GetFloat("ContactProcessingThreshold", parms.contactProcessingThreshold);
332
333 parms.terrainFriction = pConfig.GetFloat("TerrainFriction", parms.terrainFriction);
334 parms.terrainHitFraction = pConfig.GetFloat("TerrainHitFraction", parms.terrainHitFraction);
335 parms.terrainRestitution = pConfig.GetFloat("TerrainRestitution", parms.terrainRestitution);
336 parms.avatarFriction = pConfig.GetFloat("AvatarFriction", parms.avatarFriction);
337 parms.avatarRestitution = pConfig.GetFloat("AvatarRestitution", parms.avatarRestitution);
338 parms.avatarDensity = pConfig.GetFloat("AvatarDensity", parms.avatarDensity);
339 parms.avatarCapsuleRadius = pConfig.GetFloat("AvatarCapsuleRadius", parms.avatarCapsuleRadius);
340 parms.avatarCapsuleHeight = pConfig.GetFloat("AvatarCapsuleHeight", parms.avatarCapsuleHeight);
341 parms.avatarContactProcessingThreshold = pConfig.GetFloat("AvatarContactProcessingThreshold", parms.avatarContactProcessingThreshold);
342
343 parms.maxPersistantManifoldPoolSize = pConfig.GetFloat("MaxPersistantManifoldPoolSize", parms.maxPersistantManifoldPoolSize);
344 parms.shouldDisableContactPoolDynamicAllocation = ParamBoolean(pConfig, "ShouldDisableContactPoolDynamicAllocation", parms.shouldDisableContactPoolDynamicAllocation);
345 parms.shouldForceUpdateAllAabbs = ParamBoolean(pConfig, "ShouldForceUpdateAllAabbs", parms.shouldForceUpdateAllAabbs);
346 parms.shouldRandomizeSolverOrder = ParamBoolean(pConfig, "ShouldRandomizeSolverOrder", parms.shouldRandomizeSolverOrder);
347 parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands);
348 parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching);
349 parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations);
350 270
351 // Very detailed logging for physics debugging 271 // Very detailed logging for physics debugging
352 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); 272 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
@@ -357,7 +277,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
357 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); 277 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
358 } 278 }
359 } 279 }
360 m_params[0] = parms;
361 } 280 }
362 281
363 // A helper function that handles a true/false parameter and returns the proper float number encoding 282 // A helper function that handles a true/false parameter and returns the proper float number encoding
@@ -634,6 +553,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
634 // make sure no stepping happens while we're deleting stuff 553 // make sure no stepping happens while we're deleting stuff
635 m_initialized = false; 554 m_initialized = false;
636 555
556 if (m_constraintCollection != null)
557 {
558 m_constraintCollection.Dispose();
559 m_constraintCollection = null;
560 }
561
637 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 562 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
638 { 563 {
639 kvp.Value.Destroy(); 564 kvp.Value.Destroy();
@@ -776,10 +701,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
776 } 701 }
777 702
778 // The calls to the PhysicsActors can't directly call into the physics engine 703 // The calls to the PhysicsActors can't directly call into the physics engine
779 // because it might be busy. We we delay changes to a known time. 704 // because it might be busy. We delay changes to a known time.
780 // We rely on C#'s closure to save and restore the context for the delegate. 705 // We rely on C#'s closure to save and restore the context for the delegate.
781 public void TaintedObject(TaintCallback callback) 706 public void TaintedObject(TaintCallback callback)
782 { 707 {
708 if (!m_initialized) return;
709
783 lock (_taintLock) 710 lock (_taintLock)
784 _taintedObjects.Add(callback); 711 _taintedObjects.Add(callback);
785 return; 712 return;
@@ -853,61 +780,371 @@ public class BSScene : PhysicsScene, IPhysicsParameters
853 } 780 }
854 #endregion Vehicles 781 #endregion Vehicles
855 782
856 #region Runtime settable parameters 783 #region Parameters
857 public static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[] 784
785 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
786 delegate float ParamGet(BSScene scene);
787 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
788
789 private struct ParameterDefn
790 {
791 public string name;
792 public string desc;
793 public float defaultValue;
794 public ParamUser userParam;
795 public ParamGet getter;
796 public ParamSet setter;
797 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
798 {
799 name = n;
800 desc = d;
801 defaultValue = v;
802 userParam = u;
803 getter = g;
804 setter = s;
805 }
806 }
807
808 // List of all of the externally visible parameters.
809 // For each parameter, this table maps a text name to getter and setters.
810 // A ParameterDefn() takes the following parameters:
811 // -- the text name of the parameter. This is used for console input and ini file.
812 // -- a short text description of the parameter. This shows up in the console listing.
813 // -- a delegate for fetching the parameter from the ini file.
814 // Should handle fetching the right type from the ini file and converting it.
815 // -- a delegate for getting the value as a float
816 // -- a delegate for setting the value from a float
817 //
818 // To add a new variable, it is best to find an existing definition and copy it.
819 private ParameterDefn[] ParameterDefinitions =
858 { 820 {
859 new PhysParameterEntry("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)"), 821 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
860 new PhysParameterEntry("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)"), 822 ConfigurationParameters.numericTrue,
861 new PhysParameterEntry("MaxSubStep", "In simulation step, maximum number of substeps"), 823 (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
862 new PhysParameterEntry("FixedTimeStep", "In simulation step, seconds of one substep (1/60)"), 824 (s) => { return s.NumericBool(s._meshSculptedPrim); },
863 new PhysParameterEntry("MaxObjectMass", "Maximum object mass (10000.01)"), 825 (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ),
864 new PhysParameterEntry("DetailedStats", "Frames between outputting detailed phys stats. Zero is off"), 826 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
865 827 ConfigurationParameters.numericFalse,
866 new PhysParameterEntry("DefaultFriction", "Friction factor used on new objects"), 828 (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
867 new PhysParameterEntry("DefaultDensity", "Density for new objects" ), 829 (s) => { return s.NumericBool(s._forceSimplePrimMeshing); },
868 new PhysParameterEntry("DefaultRestitution", "Bouncyness of an object" ), 830 (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ),
869 // new PhysParameterEntry("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!!)" ), 831
870 new PhysParameterEntry("Gravity", "Vertical force of gravity (negative means down)" ), 832 new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
871 833 8f,
872 new PhysParameterEntry("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)" ), 834 (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); },
873 new PhysParameterEntry("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)" ), 835 (s) => { return (float)s.m_meshLOD; },
874 new PhysParameterEntry("DeactivationTime", "Seconds before considering an object potentially static" ), 836 (s,p,l,v) => { s.m_meshLOD = (int)v; } ),
875 new PhysParameterEntry("LinearSleepingThreshold", "Seconds to measure linear movement before considering static" ), 837 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
876 new PhysParameterEntry("AngularSleepingThreshold", "Seconds to measure angular movement before considering static" ), 838 32,
877 new PhysParameterEntry("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ), 839 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); },
878 new PhysParameterEntry("CcdSweptSphereRadius", "Continuious collision detection test radius" ), 840 (s) => { return (float)s.m_sculptLOD; },
879 new PhysParameterEntry("ContactProcessingThreshold", "Distance between contacts before doing collision check" ), 841 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ),
880 // Can only change the following at initialization time. Change the INI file and reboot. 842
881 new PhysParameterEntry("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)"), 843 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
882 new PhysParameterEntry("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count"), 844 10f,
883 new PhysParameterEntry("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step"), 845 (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); },
884 new PhysParameterEntry("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction"), 846 (s) => { return (float)s.m_maxSubSteps; },
885 new PhysParameterEntry("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands"), 847 (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ),
886 new PhysParameterEntry("ShouldEnableFrictionCaching", "Enable friction computation caching"), 848 new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
887 new PhysParameterEntry("NumberOfSolverIterations", "Number of internal iterations (0 means default)"), 849 1f / 60f,
888 850 (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); },
889 new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ), 851 (s) => { return (float)s.m_fixedTimeStep; },
890 new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ), 852 (s,p,l,v) => { s.m_fixedTimeStep = v; } ),
891 853 new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
892 new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ), 854 2048f,
893 new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ), 855 (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); },
894 856 (s) => { return (float)s.m_maxCollisionsPerFrame; },
895 new PhysParameterEntry("TerrainFriction", "Factor to reduce movement against terrain surface" ), 857 (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
896 new PhysParameterEntry("TerrainHitFraction", "Distance to measure hit collisions" ), 858 new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
897 new PhysParameterEntry("TerrainRestitution", "Bouncyness" ), 859 8000f,
898 new PhysParameterEntry("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation." ), 860 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
899 new PhysParameterEntry("AvatarDensity", "Density of an avatar. Changed on avatar recreation." ), 861 (s) => { return (float)s.m_maxUpdatesPerFrame; },
900 new PhysParameterEntry("AvatarRestitution", "Bouncyness. Changed on avatar recreation." ), 862 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
901 new PhysParameterEntry("AvatarCapsuleRadius", "Radius of space around an avatar" ), 863 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
902 new PhysParameterEntry("AvatarCapsuleHeight", "Default height of space around avatar" ), 864 10000.01f,
903 new PhysParameterEntry("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions") 865 (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); },
866 (s) => { return (float)s.m_maximumObjectMass; },
867 (s,p,l,v) => { s.m_maximumObjectMass = v; } ),
868
869 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
870 2200f,
871 (s,cf,p,v) => { s.PID_D = cf.GetFloat(p, v); },
872 (s) => { return (float)s.PID_D; },
873 (s,p,l,v) => { s.PID_D = v; } ),
874 new ParameterDefn("PID_P", "Parameteric factor for motion smoothing",
875 900f,
876 (s,cf,p,v) => { s.PID_P = cf.GetFloat(p, v); },
877 (s) => { return (float)s.PID_P; },
878 (s,p,l,v) => { s.PID_P = v; } ),
879
880 new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
881 0.5f,
882 (s,cf,p,v) => { s.m_params[0].defaultFriction = cf.GetFloat(p, v); },
883 (s) => { return s.m_params[0].defaultFriction; },
884 (s,p,l,v) => { s.m_params[0].defaultFriction = v; } ),
885 new ParameterDefn("DefaultDensity", "Density for new objects" ,
886 10.000006836f, // Aluminum g/cm3
887 (s,cf,p,v) => { s.m_params[0].defaultDensity = cf.GetFloat(p, v); },
888 (s) => { return s.m_params[0].defaultDensity; },
889 (s,p,l,v) => { s.m_params[0].defaultDensity = v; } ),
890 new ParameterDefn("DefaultRestitution", "Bouncyness of an object" ,
891 0f,
892 (s,cf,p,v) => { s.m_params[0].defaultRestitution = cf.GetFloat(p, v); },
893 (s) => { return s.m_params[0].defaultRestitution; },
894 (s,p,l,v) => { s.m_params[0].defaultRestitution = v; } ),
895 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
896 0f,
897 (s,cf,p,v) => { s.m_params[0].collisionMargin = cf.GetFloat(p, v); },
898 (s) => { return s.m_params[0].collisionMargin; },
899 (s,p,l,v) => { s.m_params[0].collisionMargin = v; } ),
900 new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)",
901 -9.80665f,
902 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); },
903 (s) => { return s.m_params[0].gravity; },
904 (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ),
905
906
907 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
908 0f,
909 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
910 (s) => { return s.m_params[0].linearDamping; },
911 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ),
912 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
913 0f,
914 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
915 (s) => { return s.m_params[0].angularDamping; },
916 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ),
917 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
918 0.2f,
919 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
920 (s) => { return s.m_params[0].deactivationTime; },
921 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ),
922 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
923 0.8f,
924 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
925 (s) => { return s.m_params[0].linearSleepingThreshold; },
926 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
927 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
928 1.0f,
929 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
930 (s) => { return s.m_params[0].angularSleepingThreshold; },
931 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
932 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
933 0f, // set to zero to disable
934 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
935 (s) => { return s.m_params[0].ccdMotionThreshold; },
936 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
937 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
938 0f,
939 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
940 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
941 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
942 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
943 0.1f,
944 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
945 (s) => { return s.m_params[0].contactProcessingThreshold; },
946 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
947
948 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
949 0.5f,
950 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); },
951 (s) => { return s.m_params[0].terrainFriction; },
952 (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ),
953 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
954 0.8f,
955 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); },
956 (s) => { return s.m_params[0].terrainHitFraction; },
957 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ),
958 new ParameterDefn("TerrainRestitution", "Bouncyness" ,
959 0f,
960 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); },
961 (s) => { return s.m_params[0].terrainRestitution; },
962 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
963 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
964 0.5f,
965 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
966 (s) => { return s.m_params[0].avatarFriction; },
967 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ),
968 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
969 60f,
970 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
971 (s) => { return s.m_params[0].avatarDensity; },
972 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ),
973 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
974 0f,
975 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
976 (s) => { return s.m_params[0].avatarRestitution; },
977 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ),
978 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar",
979 0.37f,
980 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); },
981 (s) => { return s.m_params[0].avatarCapsuleRadius; },
982 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
983 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
984 1.5f,
985 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
986 (s) => { return s.m_params[0].avatarCapsuleHeight; },
987 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
988 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
989 0.1f,
990 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
991 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
992 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
993
994
995 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)",
996 0f, // zero to disable
997 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
998 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
999 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
1000 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
1001 ConfigurationParameters.numericTrue,
1002 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1003 (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; },
1004 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ),
1005 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
1006 ConfigurationParameters.numericFalse,
1007 (s,cf,p,v) => { s.m_params[0].shouldForceUpdateAllAabbs = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1008 (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; },
1009 (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ),
1010 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
1011 ConfigurationParameters.numericFalse,
1012 (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1013 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
1014 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
1015 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
1016 ConfigurationParameters.numericFalse,
1017 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1018 (s) => { return s.m_params[0].shouldSplitSimulationIslands; },
1019 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ),
1020 new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching",
1021 ConfigurationParameters.numericFalse,
1022 (s,cf,p,v) => { s.m_params[0].shouldEnableFrictionCaching = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1023 (s) => { return s.m_params[0].shouldEnableFrictionCaching; },
1024 (s,p,l,v) => { s.m_params[0].shouldEnableFrictionCaching = v; } ),
1025 new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
1026 0f, // zero says use Bullet default
1027 (s,cf,p,v) => { s.m_params[0].numberOfSolverIterations = cf.GetFloat(p, v); },
1028 (s) => { return s.m_params[0].numberOfSolverIterations; },
1029 (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ),
1030
1031 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
1032 ConfigurationParameters.numericFalse,
1033 (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1034 (s) => { return s.m_params[0].linkConstraintUseFrameOffset; },
1035 (s,p,l,v) => { s.m_params[0].linkConstraintUseFrameOffset = v; } ),
1036 new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
1037 ConfigurationParameters.numericTrue,
1038 (s,cf,p,v) => { s.m_params[0].linkConstraintEnableTransMotor = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1039 (s) => { return s.m_params[0].linkConstraintEnableTransMotor; },
1040 (s,p,l,v) => { s.m_params[0].linkConstraintEnableTransMotor = v; } ),
1041 new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
1042 5.0f,
1043 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
1044 (s) => { return s.m_params[0].linkConstraintTransMotorMaxVel; },
1045 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = v; } ),
1046 new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
1047 0.1f,
1048 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
1049 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1050 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
1051
1052 new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)",
1053 0f,
1054 (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); },
1055 (s) => { return (float)s.m_detailedStatsStep; },
1056 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ),
1057 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
1058 ConfigurationParameters.numericFalse,
1059 (s,cf,p,v) => { s.shouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
1060 (s) => { return s.NumericBool(s.shouldDebugLog); },
1061 (s,p,l,v) => { s.shouldDebugLog = s.BoolNumeric(v); } ),
904 1062
905 }; 1063 };
906 1064
1065 // Convert a boolean to our numeric true and false values
1066 public float NumericBool(bool b)
1067 {
1068 return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse);
1069 }
1070
1071 // Convert numeric true and false values to a boolean
1072 public bool BoolNumeric(float b)
1073 {
1074 return (b == ConfigurationParameters.numericTrue ? true : false);
1075 }
1076
1077 // Search through the parameter definitions and return the matching
1078 // ParameterDefn structure.
1079 // Case does not matter as names are compared after converting to lower case.
1080 // Returns 'false' if the parameter is not found.
1081 private bool TryGetParameter(string paramName, out ParameterDefn defn)
1082 {
1083 bool ret = false;
1084 ParameterDefn foundDefn = new ParameterDefn();
1085 string pName = paramName.ToLower();
1086
1087 foreach (ParameterDefn parm in ParameterDefinitions)
1088 {
1089 if (pName == parm.name.ToLower())
1090 {
1091 foundDefn = parm;
1092 ret = true;
1093 break;
1094 }
1095 }
1096 defn = foundDefn;
1097 return ret;
1098 }
1099
1100 // Pass through the settable parameters and set the default values
1101 private void SetParameterDefaultValues()
1102 {
1103 foreach (ParameterDefn parm in ParameterDefinitions)
1104 {
1105 parm.setter(this, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue);
1106 }
1107 }
1108
1109 // Get user set values out of the ini file.
1110 private void SetParameterConfigurationValues(IConfig cfg)
1111 {
1112 foreach (ParameterDefn parm in ParameterDefinitions)
1113 {
1114 parm.userParam(this, cfg, parm.name, parm.defaultValue);
1115 }
1116 }
1117
1118 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
1119
1120 private void BuildParameterTable()
1121 {
1122 if (SettableParameters.Length < ParameterDefinitions.Length)
1123 {
1124
1125 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
1126 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
1127 {
1128 ParameterDefn pd = ParameterDefinitions[ii];
1129 entries.Add(new PhysParameterEntry(pd.name, pd.desc));
1130 }
1131
1132 // make the list in alphabetical order for estetic reasons
1133 entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2)
1134 {
1135 return ppe1.name.CompareTo(ppe2.name);
1136 });
1137
1138 SettableParameters = entries.ToArray();
1139 }
1140 }
1141
1142
907 #region IPhysicsParameters 1143 #region IPhysicsParameters
908 // Get the list of parameters this physics engine supports 1144 // Get the list of parameters this physics engine supports
909 public PhysParameterEntry[] GetParameterList() 1145 public PhysParameterEntry[] GetParameterList()
910 { 1146 {
1147 BuildParameterTable();
911 return SettableParameters; 1148 return SettableParameters;
912 } 1149 }
913 1150
@@ -919,63 +1156,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
919 // value activated ('terrainFriction' for instance). 1156 // value activated ('terrainFriction' for instance).
920 public bool SetPhysicsParameter(string parm, float val, uint localID) 1157 public bool SetPhysicsParameter(string parm, float val, uint localID)
921 { 1158 {
922 bool ret = true; 1159 bool ret = false;
923 string lparm = parm.ToLower(); 1160 ParameterDefn theParam;
924 switch (lparm) 1161 if (TryGetParameter(parm, out theParam))
925 { 1162 {
926 case "detailedstats": m_detailedStatsStep = (int)val; break; 1163 theParam.setter(this, parm, localID, val);
927 1164 ret = true;
928 case "meshlod": m_meshLOD = (int)val; break;
929 case "sculptlod": m_sculptLOD = (int)val; break;
930 case "maxsubstep": m_maxSubSteps = (int)val; break;
931 case "fixedtimestep": m_fixedTimeStep = val; break;
932 case "maxobjectmass": m_maximumObjectMass = val; break;
933
934 case "defaultfriction": m_params[0].defaultFriction = val; break;
935 case "defaultdensity": m_params[0].defaultDensity = val; break;
936 case "defaultrestitution": m_params[0].defaultRestitution = val; break;
937 case "collisionmargin": m_params[0].collisionMargin = val; break;
938 case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, localID, val); break;
939
940 case "lineardamping": UpdateParameterPrims(ref m_params[0].linearDamping, lparm, localID, val); break;
941 case "angulardamping": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break;
942 case "deactivationtime": UpdateParameterPrims(ref m_params[0].deactivationTime, lparm, localID, val); break;
943 case "linearsleepingthreshold": UpdateParameterPrims(ref m_params[0].linearSleepingThreshold, lparm, localID, val); break;
944 case "angularsleepingthreshold": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break;
945 case "ccdmotionthreshold": UpdateParameterPrims(ref m_params[0].ccdMotionThreshold, lparm, localID, val); break;
946 case "ccdsweptsphereradius": UpdateParameterPrims(ref m_params[0].ccdSweptSphereRadius, lparm, localID, val); break;
947 case "contactprocessingthreshold": UpdateParameterPrims(ref m_params[0].contactProcessingThreshold, lparm, localID, val); break;
948 // the following are used only at initialization time so setting them makes no sense
949 // case "maxPersistantmanifoldpoolSize": m_params[0].maxPersistantManifoldPoolSize = val; break;
950 // case "shoulddisablecontactpooldynamicallocation": m_params[0].shouldDisableContactPoolDynamicAllocation = val; break;
951 // case "shouldforceupdateallaabbs": m_params[0].shouldForceUpdateAllAabbs = val; break;
952 // case "shouldrandomizesolverorder": m_params[0].shouldRandomizeSolverOrder = val; break;
953 // case "shouldsplitsimulationislands": m_params[0].shouldSplitSimulationIslands = val; break;
954 // case "shouldenablefrictioncaching": m_params[0].shouldEnableFrictionCaching = val; break;
955 // case "numberofsolveriterations": m_params[0].numberOfSolverIterations = val; break;
956
957 case "friction": TaintedUpdateParameter(lparm, localID, val); break;
958 case "restitution": TaintedUpdateParameter(lparm, localID, val); break;
959
960 // set a terrain physical feature and cause terrain to be recalculated
961 case "terrainfriction": m_params[0].terrainFriction = val; TaintedUpdateParameter("terrain", 0, val); break;
962 case "terrainhitfraction": m_params[0].terrainHitFraction = val; TaintedUpdateParameter("terrain", 0, val); break;
963 case "terrainrestitution": m_params[0].terrainRestitution = val; TaintedUpdateParameter("terrain", 0, val); break;
964 // set an avatar physical feature and cause avatar(s) to be recalculated
965 case "avatarfriction": UpdateParameterAvatars(ref m_params[0].avatarFriction, "avatar", localID, val); break;
966 case "avatardensity": UpdateParameterAvatars(ref m_params[0].avatarDensity, "avatar", localID, val); break;
967 case "avatarrestitution": UpdateParameterAvatars(ref m_params[0].avatarRestitution, "avatar", localID, val); break;
968 case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break;
969 case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break;
970 case "avatarcontactprocessingthreshold": UpdateParameterAvatars(ref m_params[0].avatarContactProcessingThreshold, "avatar", localID, val); break;
971
972 default: ret = false; break;
973 } 1165 }
974 return ret; 1166 return ret;
975 } 1167 }
976 1168
977 // check to see if we are updating a parameter for a particular or all of the prims 1169 // check to see if we are updating a parameter for a particular or all of the prims
978 private void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) 1170 protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val)
979 { 1171 {
980 List<uint> operateOn; 1172 List<uint> operateOn;
981 lock (m_prims) operateOn = new List<uint>(m_prims.Keys); 1173 lock (m_prims) operateOn = new List<uint>(m_prims.Keys);
@@ -983,7 +1175,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
983 } 1175 }
984 1176
985 // check to see if we are updating a parameter for a particular or all of the avatars 1177 // check to see if we are updating a parameter for a particular or all of the avatars
986 private void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val) 1178 protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val)
987 { 1179 {
988 List<uint> operateOn; 1180 List<uint> operateOn;
989 lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys); 1181 lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys);
@@ -994,7 +1186,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
994 // If the local ID is APPLY_TO_NONE, just change the default value 1186 // If the local ID is APPLY_TO_NONE, just change the default value
995 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs 1187 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
996 // If the localID is a specific object, apply the parameter change to only that object 1188 // If the localID is a specific object, apply the parameter change to only that object
997 private void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val) 1189 protected void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val)
998 { 1190 {
999 switch (localID) 1191 switch (localID)
1000 { 1192 {
@@ -1021,7 +1213,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1021 } 1213 }
1022 1214
1023 // schedule the actual updating of the paramter to when the phys engine is not busy 1215 // schedule the actual updating of the paramter to when the phys engine is not busy
1024 private void TaintedUpdateParameter(string parm, uint localID, float val) 1216 protected void TaintedUpdateParameter(string parm, uint localID, float val)
1025 { 1217 {
1026 uint xlocalID = localID; 1218 uint xlocalID = localID;
1027 string xparm = parm.ToLower(); 1219 string xparm = parm.ToLower();
@@ -1036,50 +1228,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1036 public bool GetPhysicsParameter(string parm, out float value) 1228 public bool GetPhysicsParameter(string parm, out float value)
1037 { 1229 {
1038 float val = 0f; 1230 float val = 0f;
1039 bool ret = true; 1231 bool ret = false;
1040 switch (parm.ToLower()) 1232 ParameterDefn theParam;
1233 if (TryGetParameter(parm, out theParam))
1041 { 1234 {
1042 case "detailedstats": val = (int)m_detailedStatsStep; break; 1235 val = theParam.getter(this);
1043 case "meshlod": val = (float)m_meshLOD; break; 1236 ret = true;
1044 case "sculptlod": val = (float)m_sculptLOD; break;
1045 case "maxsubstep": val = (float)m_maxSubSteps; break;
1046 case "fixedtimestep": val = m_fixedTimeStep; break;
1047 case "maxobjectmass": val = m_maximumObjectMass; break;
1048
1049 case "defaultfriction": val = m_params[0].defaultFriction; break;
1050 case "defaultdensity": val = m_params[0].defaultDensity; break;
1051 case "defaultrestitution": val = m_params[0].defaultRestitution; break;
1052 case "collisionmargin": val = m_params[0].collisionMargin; break;
1053 case "gravity": val = m_params[0].gravity; break;
1054
1055 case "lineardamping": val = m_params[0].linearDamping; break;
1056 case "angulardamping": val = m_params[0].angularDamping; break;
1057 case "deactivationtime": val = m_params[0].deactivationTime; break;
1058 case "linearsleepingthreshold": val = m_params[0].linearSleepingThreshold; break;
1059 case "angularsleepingthreshold": val = m_params[0].angularDamping; break;
1060 case "ccdmotionthreshold": val = m_params[0].ccdMotionThreshold; break;
1061 case "ccdsweptsphereradius": val = m_params[0].ccdSweptSphereRadius; break;
1062 case "contactprocessingthreshold": val = m_params[0].contactProcessingThreshold; break;
1063 case "maxPersistantmanifoldpoolSize": val = m_params[0].maxPersistantManifoldPoolSize; break;
1064 case "shoulddisablecontactpooldynamicallocation": val = m_params[0].shouldDisableContactPoolDynamicAllocation; break;
1065 case "shouldforceupdateallaabbs": val = m_params[0].shouldForceUpdateAllAabbs; break;
1066 case "shouldrandomizesolverorder": val = m_params[0].shouldRandomizeSolverOrder; break;
1067 case "shouldsplitsimulationislands": val = m_params[0].shouldSplitSimulationIslands; break;
1068 case "shouldenablefrictioncaching": val = m_params[0].shouldEnableFrictionCaching; break;
1069 case "numberofsolveriterations": val = m_params[0].numberOfSolverIterations; break;
1070
1071 case "terrainfriction": val = m_params[0].terrainFriction; break;
1072 case "terrainhitfraction": val = m_params[0].terrainHitFraction; break;
1073 case "terrainrestitution": val = m_params[0].terrainRestitution; break;
1074
1075 case "avatarfriction": val = m_params[0].avatarFriction; break;
1076 case "avatardensity": val = m_params[0].avatarDensity; break;
1077 case "avatarrestitution": val = m_params[0].avatarRestitution; break;
1078 case "avatarcapsuleradius": val = m_params[0].avatarCapsuleRadius; break;
1079 case "avatarcapsuleheight": val = m_params[0].avatarCapsuleHeight; break;
1080 case "avatarcontactprocessingthreshold": val = m_params[0].avatarContactProcessingThreshold; break;
1081 default: ret = false; break;
1082
1083 } 1237 }
1084 value = val; 1238 value = val;
1085 return ret; 1239 return ret;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 54a8cfd..65e3145 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -32,6 +32,28 @@ using OpenMetaverse;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin { 33namespace OpenSim.Region.Physics.BulletSPlugin {
34 34
35// Classes to allow some type checking for the API
36public struct BulletSim
37{
38 public BulletSim(uint id, IntPtr xx) { ID = id; Ptr = xx; }
39 public IntPtr Ptr;
40 public uint ID;
41}
42
43public struct BulletBody
44{
45 public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; }
46 public IntPtr Ptr;
47 public uint ID;
48}
49
50public struct BulletConstraint
51{
52 public BulletConstraint(IntPtr xx) { Ptr = xx; }
53 public IntPtr Ptr;
54}
55
56// ===============================================================================
35[StructLayout(LayoutKind.Sequential)] 57[StructLayout(LayoutKind.Sequential)]
36public struct ConvexHull 58public struct ConvexHull
37{ 59{
@@ -142,6 +164,11 @@ public struct ConfigurationParameters
142 public float shouldEnableFrictionCaching; 164 public float shouldEnableFrictionCaching;
143 public float numberOfSolverIterations; 165 public float numberOfSolverIterations;
144 166
167 public float linkConstraintUseFrameOffset;
168 public float linkConstraintEnableTransMotor;
169 public float linkConstraintTransMotorMaxVel;
170 public float linkConstraintTransMotorMaxForce;
171
145 public const float numericTrue = 1f; 172 public const float numericTrue = 1f;
146 public const float numericFalse = 0f; 173 public const float numericFalse = 0f;
147} 174}
@@ -162,6 +189,7 @@ public enum CollisionFlags : uint
162 PHYSICAL_OBJECT = 1 << 12, 189 PHYSICAL_OBJECT = 1 << 12,
163}; 190};
164 191
192// ===============================================================================
165static class BulletSimAPI { 193static class BulletSimAPI {
166 194
167[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 195[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -211,6 +239,7 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey);
211[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 239[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
212public static extern bool CreateObject(uint worldID, ShapeData shapeData); 240public static extern bool CreateObject(uint worldID, ShapeData shapeData);
213 241
242/* Remove old functionality
214[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 243[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
215public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas); 244public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas);
216 245
@@ -225,6 +254,7 @@ public static extern bool RemoveConstraintByID(uint worldID, uint id1);
225 254
226[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 255[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
227public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2); 256public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2);
257 */
228 258
229[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 259[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
230public static extern Vector3 GetObjectPosition(uint WorldID, uint id); 260public static extern Vector3 GetObjectPosition(uint WorldID, uint id);
@@ -350,8 +380,22 @@ public static extern IntPtr CreateObject2(IntPtr sim, ShapeData shapeData);
350[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 380[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
351public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2, 381public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2,
352 Vector3 frame1loc, Quaternion frame1rot, 382 Vector3 frame1loc, Quaternion frame1rot,
353 Vector3 frame2loc, Quaternion frame2rot, 383 Vector3 frame2loc, Quaternion frame2rot);
354 Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular); 384
385[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
386public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
387
388[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
389public static extern bool SetAngularLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
390
391[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
392public static extern bool UseFrameOffset2(IntPtr constrain, float enable);
393
394[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
395public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce);
396
397[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
398public static extern bool CalculateTransforms2(IntPtr constrain);
355 399
356[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 400[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
357public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain); 401public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain);
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index 32e81e2..929b019 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -290,7 +290,6 @@ namespace OpenSim.Region.Physics.OdePlugin
290 290
291 private readonly IntPtr contactgroup; 291 private readonly IntPtr contactgroup;
292 292
293 internal IntPtr LandGeom;
294 internal IntPtr WaterGeom; 293 internal IntPtr WaterGeom;
295 294
296 private float nmTerrainContactFriction = 255.0f; 295 private float nmTerrainContactFriction = 255.0f;
@@ -489,6 +488,8 @@ namespace OpenSim.Region.Physics.OdePlugin
489 /// </summary> 488 /// </summary>
490 internal Object OdeLock = new Object(); 489 internal Object OdeLock = new Object();
491 490
491 private bool _worldInitialized = false;
492
492 public IMesher mesher; 493 public IMesher mesher;
493 494
494 private IConfigSource m_config; 495 private IConfigSource m_config;
@@ -875,6 +876,8 @@ namespace OpenSim.Region.Physics.OdePlugin
875 staticPrimspace[i, j] = IntPtr.Zero; 876 staticPrimspace[i, j] = IntPtr.Zero;
876 } 877 }
877 } 878 }
879
880 _worldInitialized = true;
878 } 881 }
879 882
880// internal void waitForSpaceUnlock(IntPtr space) 883// internal void waitForSpaceUnlock(IntPtr space)
@@ -1508,8 +1511,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1508 { 1511 {
1509 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) 1512 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f)
1510 && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) 1513 && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f)
1511 && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) 1514 && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)))
1512 && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom)
1513 { 1515 {
1514 if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f) 1516 if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f)
1515 { 1517 {
@@ -1538,7 +1540,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1538 //d.GeomGetAABB(contactGeom.g2, out aabb2); 1540 //d.GeomGetAABB(contactGeom.g2, out aabb2);
1539 //d.GeomGetAABB(contactGeom.g1, out aabb1); 1541 //d.GeomGetAABB(contactGeom.g1, out aabb1);
1540 //aabb1. 1542 //aabb1.
1541 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) 1543 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)))
1542 { 1544 {
1543 if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z) 1545 if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z)
1544 { 1546 {
@@ -2896,6 +2898,8 @@ namespace OpenSim.Region.Physics.OdePlugin
2896 /// <returns>The number of frames simulated over that period.</returns> 2898 /// <returns>The number of frames simulated over that period.</returns>
2897 public override float Simulate(float timeStep) 2899 public override float Simulate(float timeStep)
2898 { 2900 {
2901 if (!_worldInitialized) return 11f;
2902
2899 int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0; 2903 int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0;
2900 int tempTick = 0, tempTick2 = 0; 2904 int tempTick = 0, tempTick2 = 0;
2901 2905
@@ -4017,6 +4021,8 @@ namespace OpenSim.Region.Physics.OdePlugin
4017 4021
4018 public override void Dispose() 4022 public override void Dispose()
4019 { 4023 {
4024 _worldInitialized = false;
4025
4020 m_rayCastManager.Dispose(); 4026 m_rayCastManager.Dispose();
4021 m_rayCastManager = null; 4027 m_rayCastManager = null;
4022 4028
@@ -4037,6 +4043,7 @@ namespace OpenSim.Region.Physics.OdePlugin
4037 d.WorldDestroy(world); 4043 d.WorldDestroy(world);
4038 //d.CloseODE(); 4044 //d.CloseODE();
4039 } 4045 }
4046
4040 } 4047 }
4041 4048
4042 public override Dictionary<uint, float> GetTopColliders() 4049 public override Dictionary<uint, float> GetTopColliders()