aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs53
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs5
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs206
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs44
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs41
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs17
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsActor.cs3
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs3
8 files changed, 284 insertions, 88 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 7f94666..3afd52e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -70,6 +70,17 @@ public abstract class BSLinkset
70 return ret; 70 return ret;
71 } 71 }
72 72
73 public class BSLinkInfo
74 {
75 public BSPrimLinkable member;
76 public BSLinkInfo(BSPrimLinkable pMember)
77 {
78 member = pMember;
79 }
80 }
81
82 public LinksetImplementation LinksetImpl { get; protected set; }
83
73 public BSPrimLinkable LinksetRoot { get; protected set; } 84 public BSPrimLinkable LinksetRoot { get; protected set; }
74 85
75 protected BSScene m_physicsScene { get; private set; } 86 protected BSScene m_physicsScene { get; private set; }
@@ -78,7 +89,8 @@ public abstract class BSLinkset
78 public int LinksetID { get; private set; } 89 public int LinksetID { get; private set; }
79 90
80 // The children under the root in this linkset. 91 // The children under the root in this linkset.
81 protected HashSet<BSPrimLinkable> m_children; 92 // protected HashSet<BSPrimLinkable> m_children;
93 protected Dictionary<BSPrimLinkable, BSLinkInfo> m_children;
82 94
83 // We lock the diddling of linkset classes to prevent any badness. 95 // We lock the diddling of linkset classes to prevent any badness.
84 // This locks the modification of the instances of this class. Changes 96 // This locks the modification of the instances of this class. Changes
@@ -109,7 +121,7 @@ public abstract class BSLinkset
109 m_nextLinksetID = 1; 121 m_nextLinksetID = 1;
110 m_physicsScene = scene; 122 m_physicsScene = scene;
111 LinksetRoot = parent; 123 LinksetRoot = parent;
112 m_children = new HashSet<BSPrimLinkable>(); 124 m_children = new Dictionary<BSPrimLinkable, BSLinkInfo>();
113 LinksetMass = parent.RawMass; 125 LinksetMass = parent.RawMass;
114 Rebuilding = false; 126 Rebuilding = false;
115 127
@@ -170,17 +182,7 @@ public abstract class BSLinkset
170 bool ret = false; 182 bool ret = false;
171 lock (m_linksetActivityLock) 183 lock (m_linksetActivityLock)
172 { 184 {
173 ret = m_children.Contains(child); 185 ret = m_children.ContainsKey(child);
174 /* Safer version but the above should work
175 foreach (BSPrimLinkable bp in m_children)
176 {
177 if (child.LocalID == bp.LocalID)
178 {
179 ret = true;
180 break;
181 }
182 }
183 */
184 } 186 }
185 return ret; 187 return ret;
186 } 188 }
@@ -194,7 +196,24 @@ public abstract class BSLinkset
194 lock (m_linksetActivityLock) 196 lock (m_linksetActivityLock)
195 { 197 {
196 action(LinksetRoot); 198 action(LinksetRoot);
197 foreach (BSPrimLinkable po in m_children) 199 foreach (BSPrimLinkable po in m_children.Keys)
200 {
201 if (action(po))
202 break;
203 }
204 }
205 return ret;
206 }
207
208 // Perform an action on each member of the linkset including root prim.
209 // Depends on the action on whether this should be done at taint time.
210 public delegate bool ForEachLinkInfoAction(BSLinkInfo obj);
211 public virtual bool ForEachLinkInfo(ForEachLinkInfoAction action)
212 {
213 bool ret = false;
214 lock (m_linksetActivityLock)
215 {
216 foreach (BSLinkInfo po in m_children.Values)
198 { 217 {
199 if (action(po)) 218 if (action(po))
200 break; 219 break;
@@ -364,7 +383,7 @@ public abstract class BSLinkset
364 { 383 {
365 lock (m_linksetActivityLock) 384 lock (m_linksetActivityLock)
366 { 385 {
367 foreach (BSPrimLinkable bp in m_children) 386 foreach (BSPrimLinkable bp in m_children.Keys)
368 { 387 {
369 mass += bp.RawMass; 388 mass += bp.RawMass;
370 } 389 }
@@ -382,7 +401,7 @@ public abstract class BSLinkset
382 com = LinksetRoot.Position * LinksetRoot.RawMass; 401 com = LinksetRoot.Position * LinksetRoot.RawMass;
383 float totalMass = LinksetRoot.RawMass; 402 float totalMass = LinksetRoot.RawMass;
384 403
385 foreach (BSPrimLinkable bp in m_children) 404 foreach (BSPrimLinkable bp in m_children.Keys)
386 { 405 {
387 com += bp.Position * bp.RawMass; 406 com += bp.Position * bp.RawMass;
388 totalMass += bp.RawMass; 407 totalMass += bp.RawMass;
@@ -401,7 +420,7 @@ public abstract class BSLinkset
401 { 420 {
402 com = LinksetRoot.Position; 421 com = LinksetRoot.Position;
403 422
404 foreach (BSPrimLinkable bp in m_children) 423 foreach (BSPrimLinkable bp in m_children.Keys)
405 { 424 {
406 com += bp.Position; 425 com += bp.Position;
407 } 426 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index 6359046..085d195 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -42,6 +42,7 @@ public sealed class BSLinksetCompound : BSLinkset
42 public BSLinksetCompound(BSScene scene, BSPrimLinkable parent) 42 public BSLinksetCompound(BSScene scene, BSPrimLinkable parent)
43 : base(scene, parent) 43 : base(scene, parent)
44 { 44 {
45 LinksetImpl = LinksetImplementation.Compound;
45 } 46 }
46 47
47 // ================================================================ 48 // ================================================================
@@ -257,7 +258,7 @@ public sealed class BSLinksetCompound : BSLinkset
257 { 258 {
258 if (!HasChild(child)) 259 if (!HasChild(child))
259 { 260 {
260 m_children.Add(child); 261 m_children.Add(child, new BSLinkInfo(child));
261 262
262 DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); 263 DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
263 264
@@ -353,7 +354,7 @@ public sealed class BSLinksetCompound : BSLinkset
353 354
354 // Add the shapes of all the components of the linkset 355 // Add the shapes of all the components of the linkset
355 int memberIndex = 1; 356 int memberIndex = 1;
356 ForEachMember(delegate(BSPrimLinkable cPrim) 357 ForEachMember((cPrim) =>
357 { 358 {
358 if (IsRoot(cPrim)) 359 if (IsRoot(cPrim))
359 { 360 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
index f17d698..4bac222 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
@@ -36,8 +36,78 @@ public sealed class BSLinksetConstraints : BSLinkset
36{ 36{
37 // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; 37 // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";
38 38
39 public class BSLinkInfoConstraint : BSLinkInfo
40 {
41 public ConstraintType constraintType;
42 public BSConstraint constraint;
43 public OMV.Vector3 linearLimitLow;
44 public OMV.Vector3 linearLimitHigh;
45 public OMV.Vector3 angularLimitLow;
46 public OMV.Vector3 angularLimitHigh;
47 public bool useFrameOffset;
48 public bool enableTransMotor;
49 public float transMotorMaxVel;
50 public float transMotorMaxForce;
51 public float cfm;
52 public float erp;
53 public float solverIterations;
54
55 public BSLinkInfoConstraint(BSPrimLinkable pMember)
56 : base(pMember)
57 {
58 constraint = null;
59 ResetToFixedConstraint();
60 }
61
62 // Set all the parameters for this constraint to a fixed, non-movable constraint.
63 public void ResetToFixedConstraint()
64 {
65 constraintType = ConstraintType.D6_CONSTRAINT_TYPE;
66 linearLimitLow = OMV.Vector3.Zero;
67 linearLimitHigh = OMV.Vector3.Zero;
68 angularLimitLow = OMV.Vector3.Zero;
69 angularLimitHigh = OMV.Vector3.Zero;
70 useFrameOffset = BSParam.LinkConstraintUseFrameOffset;
71 enableTransMotor = BSParam.LinkConstraintEnableTransMotor;
72 transMotorMaxVel = BSParam.LinkConstraintTransMotorMaxVel;
73 transMotorMaxForce = BSParam.LinkConstraintTransMotorMaxForce;
74 cfm = BSParam.LinkConstraintCFM;
75 erp = BSParam.LinkConstraintERP;
76 solverIterations = BSParam.LinkConstraintSolverIterations;
77 }
78
79 // Given a constraint, apply the current constraint parameters to same.
80 public void SetConstraintParameters(BSConstraint constrain)
81 {
82 switch (constraintType)
83 {
84 case ConstraintType.D6_CONSTRAINT_TYPE:
85 BSConstraint6Dof constrain6dof = constrain as BSConstraint6Dof;
86 if (constrain6dof != null)
87 {
88 // zero linear and angular limits makes the objects unable to move in relation to each other
89 constrain6dof.SetLinearLimits(linearLimitLow, linearLimitHigh);
90 constrain6dof.SetAngularLimits(angularLimitLow, angularLimitHigh);
91
92 // tweek the constraint to increase stability
93 constrain6dof.UseFrameOffset(useFrameOffset);
94 constrain6dof.TranslationalLimitMotor(enableTransMotor, transMotorMaxVel, transMotorMaxForce);
95 constrain6dof.SetCFMAndERP(cfm, erp);
96 if (solverIterations != 0f)
97 {
98 constrain6dof.SetSolverIterations(solverIterations);
99 }
100 }
101 break;
102 default:
103 break;
104 }
105 }
106 }
107
39 public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent) 108 public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent)
40 { 109 {
110 LinksetImpl = LinksetImplementation.Constraint;
41 } 111 }
42 112
43 // When physical properties are changed the linkset needs to recalculate 113 // When physical properties are changed the linkset needs to recalculate
@@ -142,7 +212,7 @@ public sealed class BSLinksetConstraints : BSLinkset
142 { 212 {
143 if (!HasChild(child)) 213 if (!HasChild(child))
144 { 214 {
145 m_children.Add(child); 215 m_children.Add(child, new BSLinkInfoConstraint(child));
146 216
147 DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); 217 DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
148 218
@@ -190,73 +260,74 @@ public sealed class BSLinksetConstraints : BSLinkset
190 } 260 }
191 261
192 // Create a static constraint between the two passed objects 262 // Create a static constraint between the two passed objects
193 private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSPrimLinkable childPrim) 263 private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li)
194 { 264 {
265 BSLinkInfoConstraint liConstraint = li as BSLinkInfoConstraint;
266 if (liConstraint == null)
267 return null;
268
195 // Zero motion for children so they don't interpolate 269 // Zero motion for children so they don't interpolate
196 childPrim.ZeroMotion(true); 270 li.member.ZeroMotion(true);
197
198 // Relative position normalized to the root prim
199 // Essentually a vector pointing from center of rootPrim to center of childPrim
200 OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;
201
202 // real world coordinate of midpoint between the two objects
203 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
204
205 DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
206 rootPrim.LocalID,
207 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
208 childPrim.LocalID, childPrim.PhysBody.AddrString,
209 rootPrim.Position, childPrim.Position, midPoint);
210
211 // create a constraint that allows no freedom of movement between the two objects
212 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
213
214 BSConstraint6Dof constrain = new BSConstraint6Dof(
215 m_physicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true );
216 // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true );
217
218 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
219 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
220 * of the objects.
221 * Code left for future programmers.
222 // ==================================================================================
223 // relative position normalized to the root prim
224 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
225 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
226
227 // relative rotation of the child to the parent
228 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
229 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
230
231 DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
232 BS6DofConstraint constrain = new BS6DofConstraint(
233 PhysicsScene.World, rootPrim.Body, childPrim.Body,
234 OMV.Vector3.Zero,
235 OMV.Quaternion.Inverse(rootPrim.Orientation),
236 OMV.Vector3.Zero,
237 OMV.Quaternion.Inverse(childPrim.Orientation),
238 true,
239 true
240 );
241 // ==================================================================================
242 */
243 271
244 m_physicsScene.Constraints.AddConstraint(constrain); 272 BSConstraint constrain = null;
245 273
246 // zero linear and angular limits makes the objects unable to move in relation to each other 274 switch (liConstraint.constraintType)
247 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
248 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
249
250 // tweek the constraint to increase stability
251 constrain.UseFrameOffset(BSParam.LinkConstraintUseFrameOffset);
252 constrain.TranslationalLimitMotor(BSParam.LinkConstraintEnableTransMotor,
253 BSParam.LinkConstraintTransMotorMaxVel,
254 BSParam.LinkConstraintTransMotorMaxForce);
255 constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP);
256 if (BSParam.LinkConstraintSolverIterations != 0f)
257 { 275 {
258 constrain.SetSolverIterations(BSParam.LinkConstraintSolverIterations); 276 case ConstraintType.D6_CONSTRAINT_TYPE:
277 // Relative position normalized to the root prim
278 // Essentually a vector pointing from center of rootPrim to center of li.member
279 OMV.Vector3 childRelativePosition = liConstraint.member.Position - rootPrim.Position;
280
281 // real world coordinate of midpoint between the two objects
282 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
283
284 DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
285 rootPrim.LocalID,
286 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
287 liConstraint.member.LocalID, liConstraint.member.PhysBody.AddrString,
288 rootPrim.Position, liConstraint.member.Position, midPoint);
289
290 // create a constraint that allows no freedom of movement between the two objects
291 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
292
293 constrain = new BSConstraint6Dof(
294 m_physicsScene.World, rootPrim.PhysBody, liConstraint.member.PhysBody, midPoint, true, true );
295
296 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
297 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
298 * of the objects.
299 * Code left for future programmers.
300 // ==================================================================================
301 // relative position normalized to the root prim
302 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
303 OMV.Vector3 childRelativePosition = (liConstraint.member.Position - rootPrim.Position) * invThisOrientation;
304
305 // relative rotation of the child to the parent
306 OMV.Quaternion childRelativeRotation = invThisOrientation * liConstraint.member.Orientation;
307 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
308
309 DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, liConstraint.member.LocalID);
310 constrain = new BS6DofConstraint(
311 PhysicsScene.World, rootPrim.Body, liConstraint.member.Body,
312 OMV.Vector3.Zero,
313 OMV.Quaternion.Inverse(rootPrim.Orientation),
314 OMV.Vector3.Zero,
315 OMV.Quaternion.Inverse(liConstraint.member.Orientation),
316 true,
317 true
318 );
319 // ==================================================================================
320 */
321
322 break;
323 default:
324 break;
259 } 325 }
326
327 liConstraint.SetConstraintParameters(constrain);
328
329 m_physicsScene.Constraints.AddConstraint(constrain);
330
260 return constrain; 331 return constrain;
261 } 332 }
262 333
@@ -317,23 +388,24 @@ public sealed class BSLinksetConstraints : BSLinkset
317 return; // Note the 'finally' clause at the botton which will get executed. 388 return; // Note the 'finally' clause at the botton which will get executed.
318 } 389 }
319 390
320 foreach (BSPrimLinkable child in m_children) 391 ForEachLinkInfo((li) =>
321 { 392 {
322 // A child in the linkset physically shows the mass of the whole linkset. 393 // A child in the linkset physically shows the mass of the whole linkset.
323 // This allows Bullet to apply enough force on the child to move the whole linkset. 394 // This allows Bullet to apply enough force on the child to move the whole linkset.
324 // (Also do the mass stuff before recomputing the constraint so mass is not zero.) 395 // (Also do the mass stuff before recomputing the constraint so mass is not zero.)
325 child.UpdatePhysicalMassProperties(linksetMass, true); 396 li.member.UpdatePhysicalMassProperties(linksetMass, true);
326 397
327 BSConstraint constrain; 398 BSConstraint constrain;
328 if (!m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) 399 if (!m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, li.member.PhysBody, out constrain))
329 { 400 {
330 // If constraint doesn't exist yet, create it. 401 // If constraint doesn't exist yet, create it.
331 constrain = BuildConstraint(LinksetRoot, child); 402 constrain = BuildConstraint(LinksetRoot, li);
332 } 403 }
333 constrain.RecomputeConstraintVariables(linksetMass); 404 constrain.RecomputeConstraintVariables(linksetMass);
334 405
335 // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG 406 // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG
336 } 407 return false; // 'false' says to keep processing other members
408 });
337 } 409 }
338 finally 410 finally
339 { 411 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index e92a1d2..a0b6abc 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -1541,6 +1541,50 @@ public class BSPrim : BSPhysObject
1541 PhysicalActors.RemoveDependencies(); 1541 PhysicalActors.RemoveDependencies();
1542 } 1542 }
1543 1543
1544 #region Extension
1545 public override object Extension(string pFunct, params object[] pParams)
1546 {
1547 object ret = null;
1548 switch (pFunct)
1549 {
1550 case BSScene.PhysFunctGetLinksetType:
1551 {
1552 BSPrimLinkable myHandle = this as BSPrimLinkable;
1553 if (myHandle != null)
1554 {
1555 ret = (object)myHandle.LinksetType;
1556 }
1557 m_log.DebugFormat("{0} Extension.physGetLinksetType, type={1}", LogHeader, ret);
1558 break;
1559 }
1560 case BSScene.PhysFunctSetLinksetType:
1561 {
1562 if (pParams.Length > 0)
1563 {
1564 BSLinkset.LinksetImplementation linksetType = (BSLinkset.LinksetImplementation)pParams[0];
1565 BSPrimLinkable myHandle = this as BSPrimLinkable;
1566 if (myHandle != null && myHandle.Linkset.IsRoot(myHandle))
1567 {
1568 PhysScene.TaintedObject("BSPrim.PhysFunctSetLinksetType", delegate()
1569 {
1570 // Cause the linkset type to change
1571 m_log.DebugFormat("{0} Extension.physSetLinksetType, oldType={1}, newType={2}",
1572 LogHeader, myHandle.Linkset.LinksetImpl, linksetType);
1573 myHandle.ConvertLinkset(linksetType);
1574 });
1575 }
1576 ret = (object)(int)linksetType;
1577 }
1578 break;
1579 }
1580 default:
1581 ret = base.Extension(pFunct, pParams);
1582 break;
1583 }
1584 return ret;
1585 }
1586 #endregion // Extension
1587
1544 // The physics engine says that properties have updated. Update same and inform 1588 // The physics engine says that properties have updated. Update same and inform
1545 // the world that things have changed. 1589 // the world that things have changed.
1546 // NOTE: BSPrim.UpdateProperties is overloaded by BSPrimLinkable which modifies updates from root and children prims. 1590 // NOTE: BSPrim.UpdateProperties is overloaded by BSPrimLinkable which modifies updates from root and children prims.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
index 2f392da..7179a6d 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
@@ -233,5 +233,46 @@ public class BSPrimLinkable : BSPrimDisplaced
233 base.HasSomeCollision = value; 233 base.HasSomeCollision = value;
234 } 234 }
235 } 235 }
236
237 // Convert the existing linkset of this prim into a new type.
238 public bool ConvertLinkset(BSLinkset.LinksetImplementation newType)
239 {
240 bool ret = false;
241 if (LinksetType != newType)
242 {
243 // Set the implementation type first so the call to BSLinkset.Factory gets the new type.
244 this.LinksetType = newType;
245
246 BSLinkset oldLinkset = this.Linkset;
247 BSLinkset newLinkset = BSLinkset.Factory(PhysScene, this);
248
249 this.Linkset = newLinkset;
250
251 // Pick up any physical dependencies this linkset might have in the physics engine.
252 oldLinkset.RemoveDependencies(this);
253
254 // Create a list of the children (mainly because can't interate through a list that's changing)
255 List<BSPrimLinkable> children = new List<BSPrimLinkable>();
256 oldLinkset.ForEachMember((child) =>
257 {
258 if (!oldLinkset.IsRoot(child))
259 children.Add(child);
260 return false; // 'false' says to continue to next member
261 });
262
263 // Remove the children from the old linkset and add to the new (will be a new instance from the factory)
264 foreach (BSPrimLinkable child in children)
265 {
266 oldLinkset.RemoveMeFromLinkset(child);
267 newLinkset.AddMeToLinkset(child);
268 child.Linkset = newLinkset;
269 }
270
271 // Force the shape and linkset to get reconstructed
272 newLinkset.Refresh(this);
273 this.ForceBodyShapeRebuild(true /* inTaintTime */);
274 }
275 return ret;
276 }
236} 277}
237} 278}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 41aca3b..79ac5a5 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -862,6 +862,23 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
862 862
863 public override bool IsThreaded { get { return false; } } 863 public override bool IsThreaded { get { return false; } }
864 864
865 #region Extensions
866 // =============================================================
867 // Per scene functions. See below.
868
869 // Per avatar functions. See BSCharacter.
870
871 // Per prim functions. See BSPrim.
872 public const string PhysFunctGetLinksetType = "BulletSim.GetLinksetType";
873 public const string PhysFunctSetLinksetType = "BulletSim.SetLinksetType";
874 // =============================================================
875
876 public override object Extension(string pFunct, params object[] pParams)
877 {
878 return base.Extension(pFunct, pParams);
879 }
880 #endregion // Extensions
881
865 #region Taints 882 #region Taints
866 // The simulation execution order is: 883 // The simulation execution order is:
867 // Simulate() 884 // Simulate()
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
index 2500f27..1750853 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
@@ -317,7 +317,8 @@ namespace OpenSim.Region.Physics.Manager
317 // Extendable interface for new, physics engine specific operations 317 // Extendable interface for new, physics engine specific operations
318 public virtual object Extension(string pFunct, params object[] pParams) 318 public virtual object Extension(string pFunct, params object[] pParams)
319 { 319 {
320 throw new NotImplementedException(); 320 // A NOP of the physics engine does not implement this feature
321 return null;
321 } 322 }
322 } 323 }
323 324
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index 07a1d36..c93206d 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -338,7 +338,8 @@ namespace OpenSim.Region.Physics.Manager
338 // Extendable interface for new, physics engine specific operations 338 // Extendable interface for new, physics engine specific operations
339 public virtual object Extension(string pFunct, params object[] pParams) 339 public virtual object Extension(string pFunct, params object[] pParams)
340 { 340 {
341 throw new NotImplementedException(); 341 // A NOP if the extension thing is not implemented by the physics engine
342 return null;
342 } 343 }
343 } 344 }
344} 345}