aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs327
1 files changed, 95 insertions, 232 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 3be28e3..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,8 +89,13 @@ 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;
@@ -133,9 +138,8 @@ public sealed class BSPrim : PhysicsActor
133 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 138 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material
134 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 139 _density = _scene.Params.defaultDensity; // TODO: compute based on object material
135 _restitution = _scene.Params.defaultRestitution; 140 _restitution = _scene.Params.defaultRestitution;
136 _parentPrim = null; // not a child or a parent 141 _linkset = new BSLinkset(_scene, this); // a linkset of one
137 _vehicle = new BSDynamics(this); // add vehicleness 142 _vehicle = new BSDynamics(this); // add vehicleness
138 _childrenPrims = new List<BSPrim>();
139 _mass = CalculateMass(); 143 _mass = CalculateMass();
140 // do the actual object creation at taint time 144 // do the actual object creation at taint time
141 _scene.TaintedObject(delegate() 145 _scene.TaintedObject(delegate()
@@ -161,16 +165,8 @@ public sealed class BSPrim : PhysicsActor
161 165
162 _scene.TaintedObject(delegate() 166 _scene.TaintedObject(delegate()
163 { 167 {
164 // undo any dependance with/on other objects 168 // Undo any links between me and any other object
165 if (_parentPrim != null) 169 _linkset = _linkset.RemoveMeFromLinkset(this);
166 {
167 // If I'm someone's child, tell them to forget about me.
168 _parentPrim.RemoveChildFromLinkset(this);
169 _parentPrim = null;
170 }
171
172 // make sure there are no other prims linked to me
173 UnlinkAllChildren();
174 170
175 // 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.
176 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); 172 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID);
@@ -187,7 +183,7 @@ public sealed class BSPrim : PhysicsActor
187 _scene.TaintedObject(delegate() 183 _scene.TaintedObject(delegate()
188 { 184 {
189 _mass = CalculateMass(); // changing size changes the mass 185 _mass = CalculateMass(); // changing size changes the mass
190 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, Mass, IsPhysical); 186 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical);
191 RecreateGeomAndObject(); 187 RecreateGeomAndObject();
192 }); 188 });
193 } 189 }
@@ -226,32 +222,8 @@ public sealed class BSPrim : PhysicsActor
226 BSPrim parent = obj as BSPrim; 222 BSPrim parent = obj as BSPrim;
227 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);
228 DetailLog("{0},link,parent={1}", LocalID, obj.LocalID); 224 DetailLog("{0},link,parent={1}", LocalID, obj.LocalID);
229 // TODO: decide if this parent checking needs to happen at taint time 225
230 if (_parentPrim == null) 226 _linkset = _linkset.AddMeToLinkset(this, parent);
231 {
232 if (parent != null)
233 {
234 // I don't have a parent so I am joining a linkset
235 parent.AddChildToLinkset(this);
236 }
237 }
238 else
239 {
240 // I already have a parent, is parenting changing?
241 if (parent != _parentPrim)
242 {
243 if (parent == null)
244 {
245 // we are being removed from a linkset
246 _parentPrim.RemoveChildFromLinkset(this);
247 }
248 else
249 {
250 // asking to reparent a prim should not happen
251 m_log.ErrorFormat("{0}: link(): Reparenting a prim. ", LogHeader);
252 }
253 }
254 }
255 return; 227 return;
256 } 228 }
257 229
@@ -260,81 +232,18 @@ public sealed class BSPrim : PhysicsActor
260 // 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
261 // 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
262 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, 234 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
263 (_parentPrim==null ? "NULL" : _parentPrim._avName+"/"+_parentPrim.LocalID.ToString())); 235 _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString());
264 DetailLog("{0},delink,parent={1}", LocalID, (_parentPrim==null ? "NULL" : _parentPrim.LocalID.ToString())); 236 DetailLog("{0},delink,parent={1}", LocalID, _linkset.Root.LocalID.ToString());
265 if (_parentPrim != null)
266 {
267 _parentPrim.RemoveChildFromLinkset(this);
268 }
269 return;
270 }
271 237
272 // I am the root of a linkset and a new child is being added 238 _linkset.RemoveMeFromLinkset(this);
273 public void AddChildToLinkset(BSPrim pchild) 239 return;
274 {
275 BSPrim child = pchild;
276 _scene.TaintedObject(delegate()
277 {
278 if (!_childrenPrims.Contains(child))
279 {
280 DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, this.LocalID);
281 DetailLog("{0},AddChildToLinkset,child={1}", LocalID, pchild.LocalID);
282 _childrenPrims.Add(child);
283 child._parentPrim = this; // the child has gained a parent
284 // RecreateGeomAndObject(); // rebuild my shape with the new child added
285 LinkAChildToMe(pchild); // build the physical binding between me and the child
286
287 _mass = CalculateMass();
288 }
289 });
290 return;
291 }
292
293 // I am the root of a linkset and one of my children is being removed.
294 // Safe to call even if the child is not really in my linkset.
295 public void RemoveChildFromLinkset(BSPrim pchild)
296 {
297 BSPrim child = pchild;
298 _scene.TaintedObject(delegate()
299 {
300 if (_childrenPrims.Contains(child))
301 {
302 DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
303 DetailLog("{0},RemoveChildFromLinkset,child={1}", LocalID, pchild.LocalID);
304 _childrenPrims.Remove(child);
305 child._parentPrim = null; // the child has lost its parent
306 if (_childrenPrims.Count == 0)
307 {
308 // if the linkset is empty, make sure all linkages have been removed
309 UnlinkAllChildren();
310 }
311 else
312 {
313 // RecreateGeomAndObject(); // rebuild my shape with the child removed
314 UnlinkAChildFromMe(pchild);
315 }
316
317 _mass = CalculateMass();
318 }
319 else
320 {
321 m_log.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset");
322 }
323 });
324 return;
325 }
326
327 // return true if we are the root of a linkset (there are children to manage)
328 public bool IsRootOfLinkset
329 {
330 get { return (_parentPrim == null && _childrenPrims.Count != 0); }
331 } 240 }
332 241
333 // Set motion values to zero. 242 // Set motion values to zero.
334 // 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.
335 // Push the setting of the values to the viewer. 244 // Push the setting of the values to the viewer.
336 // Called at taint time! 245 // Called at taint time!
337 private void ZeroMotion() 246 public void ZeroMotion()
338 { 247 {
339 _velocity = OMV.Vector3.Zero; 248 _velocity = OMV.Vector3.Zero;
340 _acceleration = OMV.Vector3.Zero; 249 _acceleration = OMV.Vector3.Zero;
@@ -355,9 +264,10 @@ public sealed class BSPrim : PhysicsActor
355 264
356 public override OMV.Vector3 Position { 265 public override OMV.Vector3 Position {
357 get { 266 get {
358 // child prims move around based on their parent. Need to get the latest location 267 if (!_linkset.IsRoot(this))
359 if (_parentPrim != null) 268 // child prims move around based on their parent. Need to get the latest location
360 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 269 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
270
361 // 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
362 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 272 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
363 return _position; 273 return _position;
@@ -373,16 +283,31 @@ public sealed class BSPrim : PhysicsActor
373 } 283 }
374 } 284 }
375 285
376 // Return the effective mass of the object. Non-physical objects do not have mass. 286 // Return the effective mass of the object.
377 public override float Mass { 287 // If there are multiple items in the linkset, add them together for the root
378 get { 288 public override float Mass
379 if (IsPhysical) 289 {
380 return _mass; 290 get
381 else 291 {
382 return 0f; 292 return _linkset.LinksetMass;
383 } 293 }
384 } 294 }
385 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
386 public override OMV.Vector3 Force { 311 public override OMV.Vector3 Force {
387 get { return _force; } 312 get { return _force; }
388 set { 313 set {
@@ -473,8 +398,6 @@ public sealed class BSPrim : PhysicsActor
473 return; 398 return;
474 } 399 }
475 400
476 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
477 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
478 public override OMV.Vector3 Velocity { 401 public override OMV.Vector3 Velocity {
479 get { return _velocity; } 402 get { return _velocity; }
480 set { 403 set {
@@ -503,9 +426,9 @@ public sealed class BSPrim : PhysicsActor
503 } 426 }
504 public override OMV.Quaternion Orientation { 427 public override OMV.Quaternion Orientation {
505 get { 428 get {
506 if (_parentPrim != null) 429 if (!_linkset.IsRoot(this))
507 { 430 {
508 // children move around because tied to parent. Get a fresh value. 431 // Children move around because tied to parent. Get a fresh value.
509 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); 432 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
510 } 433 }
511 return _orientation; 434 return _orientation;
@@ -555,14 +478,16 @@ public sealed class BSPrim : PhysicsActor
555 private void SetObjectDynamic() 478 private void SetObjectDynamic()
556 { 479 {
557 // 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);
558 // non-physical things work best with a mass of zero 481
559 if (!IsStatic) 482 RecreateGeomAndObject();
560 { 483
561 _mass = CalculateMass(); 484 float mass = _mass;
562 RecreateGeomAndObject(); 485 // Bullet wants static objects have a mass of zero
563 } 486 if (IsStatic)
564 DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, Mass); 487 mass = 0f;
565 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);
566 } 491 }
567 492
568 // prims don't fly 493 // prims don't fly
@@ -1004,6 +929,9 @@ public sealed class BSPrim : PhysicsActor
1004 929
1005 returnMass = _density * volume; 930 returnMass = _density * volume;
1006 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.
1007 if (IsRootOfLinkset) 935 if (IsRootOfLinkset)
1008 { 936 {
1009 foreach (BSPrim prim in _childrenPrims) 937 foreach (BSPrim prim in _childrenPrims)
@@ -1011,6 +939,7 @@ public sealed class BSPrim : PhysicsActor
1011 returnMass += prim.CalculateMass(); 939 returnMass += prim.CalculateMass();
1012 } 940 }
1013 } 941 }
942 */
1014 943
1015 if (returnMass <= 0) 944 if (returnMass <= 0)
1016 returnMass = 0.0001f; 945 returnMass = 0.0001f;
@@ -1026,9 +955,11 @@ public sealed class BSPrim : PhysicsActor
1026 // 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
1027 // 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
1028 // 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
1029 private void CreateGeom(bool forceRebuild) 958 // Returns 'true' if the geometry was rebuilt
959 private bool CreateGeom(bool forceRebuild)
1030 { 960 {
1031 // 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;
1032 if (!_scene.NeedsMeshing(_pbs)) 963 if (!_scene.NeedsMeshing(_pbs))
1033 { 964 {
1034 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 965 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
@@ -1036,18 +967,26 @@ public sealed class BSPrim : PhysicsActor
1036 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)
1037 { 968 {
1038 // 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);
1039 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 970 if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)
1040 DetailLog("{0},CreateGeom,sphere", LocalID); 971 {
1041 // Bullet native objects are scaled by the Bullet engine so pass the size in 972 DetailLog("{0},CreateGeom,sphere", LocalID);
1042 _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 }
1043 } 978 }
1044 } 979 }
1045 else 980 else
1046 { 981 {
1047 // 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);
1048 DetailLog("{0},CreateGeom,box", LocalID); 983 if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)
1049 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 984 {
1050 _scale = _size; 985 DetailLog("{0},CreateGeom,box", LocalID);
986 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
987 ret = true;
988 _scale = _size;
989 }
1051 } 990 }
1052 } 991 }
1053 else 992 else
@@ -1059,6 +998,7 @@ public sealed class BSPrim : PhysicsActor
1059 // physical objects require a hull for interaction. 998 // physical objects require a hull for interaction.
1060 // This will create the mesh if it doesn't already exist 999 // This will create the mesh if it doesn't already exist
1061 CreateGeomHull(); 1000 CreateGeomHull();
1001 ret = true;
1062 } 1002 }
1063 } 1003 }
1064 else 1004 else
@@ -1067,9 +1007,11 @@ public sealed class BSPrim : PhysicsActor
1067 { 1007 {
1068 // Static (non-physical) objects only need a mesh for bumping into 1008 // Static (non-physical) objects only need a mesh for bumping into
1069 CreateGeomMesh(); 1009 CreateGeomMesh();
1010 ret = true;
1070 } 1011 }
1071 } 1012 }
1072 } 1013 }
1014 return ret;
1073 } 1015 }
1074 1016
1075 // 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
@@ -1254,20 +1196,18 @@ public sealed class BSPrim : PhysicsActor
1254 // 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
1255 private void CreateObject() 1197 private void CreateObject()
1256 { 1198 {
1257 if (IsRootOfLinkset) 1199 // this routine is called when objects are rebuilt.
1258 { 1200
1259 // Create a linkset around this object 1201 // the mesh or hull must have already been created in Bullet
1260 CreateLinkset(); 1202 ShapeData shape;
1261 } 1203 FillShapeInfo(out shape);
1262 else 1204 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1263 { 1205 BulletSimAPI.CreateObject(_scene.WorldID, shape);
1264 // simple object 1206 // the CreateObject() may have recreated the rigid body. Make sure we have the latest.
1265 // the mesh or hull must have already been created in Bullet 1207 m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID);
1266 ShapeData shape; 1208
1267 FillShapeInfo(out shape); 1209 // The root object could have been recreated. Make sure everything linksety is up to date.
1268 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); 1210 _linkset.RefreshLinkset(this);
1269 BulletSimAPI.CreateObject(_scene.WorldID, shape);
1270 }
1271 } 1211 }
1272 1212
1273 // Copy prim's info into the BulletSim shape description structure 1213 // Copy prim's info into the BulletSim shape description structure
@@ -1279,7 +1219,7 @@ public sealed class BSPrim : PhysicsActor
1279 shape.Rotation = _orientation; 1219 shape.Rotation = _orientation;
1280 shape.Velocity = _velocity; 1220 shape.Velocity = _velocity;
1281 shape.Scale = _scale; 1221 shape.Scale = _scale;
1282 shape.Mass = Mass; 1222 shape.Mass = _isPhysical ? _mass : 0f;
1283 shape.Buoyancy = _buoyancy; 1223 shape.Buoyancy = _buoyancy;
1284 shape.HullKey = _hullKey; 1224 shape.HullKey = _hullKey;
1285 shape.MeshKey = _meshKey; 1225 shape.MeshKey = _meshKey;
@@ -1289,83 +1229,6 @@ public sealed class BSPrim : PhysicsActor
1289 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; 1229 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1290 } 1230 }
1291 1231
1292 #region Linkset creation and destruction
1293
1294 // Create the linkset by putting constraints between the objects of the set so they cannot move
1295 // relative to each other.
1296 void CreateLinkset()
1297 {
1298 // DebugLog("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1);
1299
1300 // remove any constraints that might be in place
1301 UnlinkAllChildren();
1302
1303 // create constraints between the root prim and each of the children
1304 foreach (BSPrim prim in _childrenPrims)
1305 {
1306 LinkAChildToMe(prim);
1307 }
1308 }
1309
1310 // Create a constraint between me (root of linkset) and the passed prim (the child).
1311 // Called at taint time!
1312 private void LinkAChildToMe(BSPrim childPrim)
1313 {
1314 // Zero motion for children so they don't interpolate
1315 childPrim.ZeroMotion();
1316
1317 // relative position normalized to the root prim
1318 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(this._orientation);
1319 OMV.Vector3 childRelativePosition = (childPrim._position - this._position) * invThisOrientation;
1320
1321 // relative rotation of the child to the parent
1322 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim._orientation;
1323
1324 // create a constraint that allows no freedom of movement between the two objects
1325 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
1326 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
1327 DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID);
1328 BSConstraint constrain = _scene.Constraints.CreateConstraint(
1329 _scene.World, this.Body, childPrim.Body,
1330 childRelativePosition,
1331 childRelativeRotation,
1332 OMV.Vector3.Zero,
1333 OMV.Quaternion.Identity);
1334 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
1335 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
1336
1337 // tweek the constraint to increase stability
1338 constrain.UseFrameOffset(_scene.BoolNumeric(_scene.Params.linkConstraintUseFrameOffset));
1339 if (_scene.BoolNumeric(_scene.Params.linkConstraintEnableTransMotor))
1340 {
1341 constrain.TranslationalLimitMotor(true,
1342 _scene.Params.linkConstraintTransMotorMaxVel,
1343 _scene.Params.linkConstraintTransMotorMaxForce);
1344 }
1345 }
1346
1347 // Remove linkage between myself and a particular child
1348 // Called at taint time!
1349 private void UnlinkAChildFromMe(BSPrim childPrim)
1350 {
1351 DebugLog("{0}: UnlinkAChildFromMe: RemoveConstraint between root prim {1} and child prim {2}",
1352 LogHeader, LocalID, childPrim.LocalID);
1353 DetailLog("{0},UnlinkAChildFromMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID);
1354 // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID);
1355 _scene.Constraints.RemoveAndDestroyConstraint(this.Body, childPrim.Body);
1356 }
1357
1358 // Remove linkage between myself and any possible children I might have
1359 // Called at taint time!
1360 private void UnlinkAllChildren()
1361 {
1362 DebugLog("{0}: UnlinkAllChildren:", LogHeader);
1363 DetailLog("{0},UnlinkAllChildren,taint", LocalID);
1364 _scene.Constraints.RemoveAndDestroyConstraint(this.Body);
1365 // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID);
1366 }
1367
1368 #endregion // Linkset creation and destruction
1369 1232
1370 // Rebuild the geometry and object. 1233 // Rebuild the geometry and object.
1371 // 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.
@@ -1443,7 +1306,7 @@ public sealed class BSPrim : PhysicsActor
1443 // 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.
1444 1307
1445 // 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.
1446 if (_parentPrim == null) 1309 if (_linkset.IsRoot(this))
1447 { 1310 {
1448 // 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
1449 _position = entprop.Position; 1312 _position = entprop.Position;