diff options
author | Robert Adams | 2012-07-26 14:54:57 -0700 |
---|---|---|
committer | Robert Adams | 2012-07-26 16:05:57 -0700 |
commit | 7d30637d51c64a582cc55d41546af8f0cfc889ba (patch) | |
tree | 50b9899f149f434bed037be91983b4b0453782b7 /OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |
parent | Merge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff) | |
download | opensim-SC-7d30637d51c64a582cc55d41546af8f0cfc889ba.zip opensim-SC-7d30637d51c64a582cc55d41546af8f0cfc889ba.tar.gz opensim-SC-7d30637d51c64a582cc55d41546af8f0cfc889ba.tar.bz2 opensim-SC-7d30637d51c64a582cc55d41546af8f0cfc889ba.tar.xz |
BulletSim: refactor all the linkset logic out of the prim class
and into its own class. The BulletSim data structures track
individual prims as linksets of 1 so most of the prim code is not
different between a linked and unlinked object.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 327 |
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..d604f9c 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.Mass; |
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; |