diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 208 |
1 files changed, 116 insertions, 92 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 71a4303..a19d6d7 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -133,10 +133,7 @@ public sealed class BSPrim : PhysicsActor | |||
133 | _parentPrim = null; // not a child or a parent | 133 | _parentPrim = null; // not a child or a parent |
134 | _vehicle = new BSDynamics(this); // add vehicleness | 134 | _vehicle = new BSDynamics(this); // add vehicleness |
135 | _childrenPrims = new List<BSPrim>(); | 135 | _childrenPrims = new List<BSPrim>(); |
136 | if (_isPhysical) | 136 | _mass = CalculateMass(); |
137 | _mass = CalculateMass(); | ||
138 | else | ||
139 | _mass = 0f; | ||
140 | // do the actual object creation at taint time | 137 | // do the actual object creation at taint time |
141 | _scene.TaintedObject(delegate() | 138 | _scene.TaintedObject(delegate() |
142 | { | 139 | { |
@@ -149,22 +146,26 @@ public sealed class BSPrim : PhysicsActor | |||
149 | { | 146 | { |
150 | // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); | 147 | // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); |
151 | // DetailLog("{0},Destroy", LocalID); | 148 | // DetailLog("{0},Destroy", LocalID); |
149 | |||
152 | // Undo any vehicle properties | 150 | // Undo any vehicle properties |
153 | _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); | 151 | _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); |
154 | _scene.RemoveVehiclePrim(this); // just to make sure | 152 | _scene.RemoveVehiclePrim(this); // just to make sure |
155 | 153 | ||
156 | // undo any dependance with/on other objects | ||
157 | if (_parentPrim != null) | ||
158 | { | ||
159 | // If I'm someone's child, tell them to forget about me. | ||
160 | _parentPrim.RemoveChildFromLinkset(this); | ||
161 | _parentPrim = null; | ||
162 | } | ||
163 | |||
164 | _scene.TaintedObject(delegate() | 154 | _scene.TaintedObject(delegate() |
165 | { | 155 | { |
156 | // undo any dependance with/on other objects | ||
157 | if (_parentPrim != null) | ||
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 | |||
166 | // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. | 167 | // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. |
167 | BulletSimAPI.DestroyObject(_scene.WorldID, _localID); | 168 | BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); |
168 | }); | 169 | }); |
169 | } | 170 | } |
170 | 171 | ||
@@ -177,8 +178,8 @@ public sealed class BSPrim : PhysicsActor | |||
177 | _size = value; | 178 | _size = value; |
178 | _scene.TaintedObject(delegate() | 179 | _scene.TaintedObject(delegate() |
179 | { | 180 | { |
180 | if (_isPhysical) _mass = CalculateMass(); // changing size changes the mass | 181 | _mass = CalculateMass(); // changing size changes the mass |
181 | BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, _mass, _isPhysical); | 182 | BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, Mass, IsPhysical); |
182 | RecreateGeomAndObject(); | 183 | RecreateGeomAndObject(); |
183 | }); | 184 | }); |
184 | } | 185 | } |
@@ -188,7 +189,7 @@ public sealed class BSPrim : PhysicsActor | |||
188 | _pbs = value; | 189 | _pbs = value; |
189 | _scene.TaintedObject(delegate() | 190 | _scene.TaintedObject(delegate() |
190 | { | 191 | { |
191 | if (_isPhysical) _mass = CalculateMass(); // changing the shape changes the mass | 192 | _mass = CalculateMass(); // changing the shape changes the mass |
192 | RecreateGeomAndObject(); | 193 | RecreateGeomAndObject(); |
193 | }); | 194 | }); |
194 | } | 195 | } |
@@ -272,7 +273,10 @@ public sealed class BSPrim : PhysicsActor | |||
272 | DetailLog("{0},AddChildToLinkset,child={1}", LocalID, pchild.LocalID); | 273 | DetailLog("{0},AddChildToLinkset,child={1}", LocalID, pchild.LocalID); |
273 | _childrenPrims.Add(child); | 274 | _childrenPrims.Add(child); |
274 | child._parentPrim = this; // the child has gained a parent | 275 | child._parentPrim = this; // the child has gained a parent |
275 | RecreateGeomAndObject(); // rebuild my shape with the new child added | 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(); | ||
276 | } | 280 | } |
277 | }); | 281 | }); |
278 | return; | 282 | return; |
@@ -288,14 +292,21 @@ public sealed class BSPrim : PhysicsActor | |||
288 | if (_childrenPrims.Contains(child)) | 292 | if (_childrenPrims.Contains(child)) |
289 | { | 293 | { |
290 | DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); | 294 | DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); |
291 | DetailLog("{0},RemoveChildToLinkset,child={1}", LocalID, pchild.LocalID); | 295 | DetailLog("{0},RemoveChildFromLinkset,child={1}", LocalID, pchild.LocalID); |
292 | if (!BulletSimAPI.RemoveConstraintByID(_scene.WorldID, child.LocalID)) | ||
293 | { | ||
294 | m_log.ErrorFormat("{0}: RemoveChildFromLinkset: Failed remove constraint for {1}", LogHeader, child.LocalID); | ||
295 | } | ||
296 | _childrenPrims.Remove(child); | 296 | _childrenPrims.Remove(child); |
297 | child._parentPrim = null; // the child has lost its parent | 297 | child._parentPrim = null; // the child has lost its parent |
298 | RecreateGeomAndObject(); // rebuild my shape with the child removed | 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(); | ||
299 | } | 310 | } |
300 | else | 311 | else |
301 | { | 312 | { |
@@ -314,12 +325,19 @@ public sealed class BSPrim : PhysicsActor | |||
314 | // Set motion values to zero. | 325 | // Set motion values to zero. |
315 | // Do it to the properties so the values get set in the physics engine. | 326 | // Do it to the properties so the values get set in the physics engine. |
316 | // Push the setting of the values to the viewer. | 327 | // Push the setting of the values to the viewer. |
328 | // Called at taint time! | ||
317 | private void ZeroMotion() | 329 | private void ZeroMotion() |
318 | { | 330 | { |
319 | Velocity = OMV.Vector3.Zero; | 331 | _velocity = OMV.Vector3.Zero; |
320 | _acceleration = OMV.Vector3.Zero; | 332 | _acceleration = OMV.Vector3.Zero; |
321 | RotationalVelocity = OMV.Vector3.Zero; | 333 | _rotationalVelocity = OMV.Vector3.Zero; |
322 | base.RequestPhysicsterseUpdate(); | 334 | |
335 | // Zero some other properties directly into the physics engine | ||
336 | IntPtr obj = BulletSimAPI.GetBodyHandleWorldID2(_scene.WorldID, LocalID); | ||
337 | BulletSimAPI.SetVelocity2(obj, OMV.Vector3.Zero); | ||
338 | BulletSimAPI.SetAngularVelocity2(obj, OMV.Vector3.Zero); | ||
339 | BulletSimAPI.SetInterpolation2(obj, OMV.Vector3.Zero, OMV.Vector3.Zero); | ||
340 | BulletSimAPI.ClearForces2(obj); | ||
323 | } | 341 | } |
324 | 342 | ||
325 | public override void LockAngularMotion(OMV.Vector3 axis) | 343 | public override void LockAngularMotion(OMV.Vector3 axis) |
@@ -347,9 +365,17 @@ public sealed class BSPrim : PhysicsActor | |||
347 | }); | 365 | }); |
348 | } | 366 | } |
349 | } | 367 | } |
368 | |||
369 | // Return the effective mass of the object. Non-physical objects do not have mass. | ||
350 | public override float Mass { | 370 | public override float Mass { |
351 | get { return _mass; } | 371 | get { |
372 | if (IsPhysical) | ||
373 | return _mass; | ||
374 | else | ||
375 | return 0f; | ||
376 | } | ||
352 | } | 377 | } |
378 | |||
353 | public override OMV.Vector3 Force { | 379 | public override OMV.Vector3 Force { |
354 | get { return _force; } | 380 | get { return _force; } |
355 | set { | 381 | set { |
@@ -429,7 +455,8 @@ public sealed class BSPrim : PhysicsActor | |||
429 | // Called from Scene when doing simulation step so we're in taint processing time. | 455 | // Called from Scene when doing simulation step so we're in taint processing time. |
430 | public void StepVehicle(float timeStep) | 456 | public void StepVehicle(float timeStep) |
431 | { | 457 | { |
432 | _vehicle.Step(timeStep); | 458 | if (IsPhysical) |
459 | _vehicle.Step(timeStep); | ||
433 | } | 460 | } |
434 | 461 | ||
435 | // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more | 462 | // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more |
@@ -526,20 +553,13 @@ public sealed class BSPrim : PhysicsActor | |||
526 | { | 553 | { |
527 | // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid); | 554 | // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid); |
528 | // non-physical things work best with a mass of zero | 555 | // non-physical things work best with a mass of zero |
529 | if (IsStatic) | 556 | if (!IsStatic) |
530 | { | ||
531 | _mass = 0f; | ||
532 | } | ||
533 | else | ||
534 | { | 557 | { |
535 | _mass = CalculateMass(); | 558 | _mass = CalculateMass(); |
536 | // If it's dynamic, make sure the hull has been created for it | ||
537 | // This shouldn't do much work if the object had previously been built | ||
538 | RecreateGeomAndObject(); | 559 | RecreateGeomAndObject(); |
539 | |||
540 | } | 560 | } |
541 | DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, _mass); | 561 | DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, Mass); |
542 | BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), _mass); | 562 | BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), Mass); |
543 | } | 563 | } |
544 | 564 | ||
545 | // prims don't fly | 565 | // prims don't fly |
@@ -1234,7 +1254,7 @@ public sealed class BSPrim : PhysicsActor | |||
1234 | if (IsRootOfLinkset) | 1254 | if (IsRootOfLinkset) |
1235 | { | 1255 | { |
1236 | // Create a linkset around this object | 1256 | // Create a linkset around this object |
1237 | CreateLinksetWithConstraints(); | 1257 | CreateLinkset(); |
1238 | } | 1258 | } |
1239 | else | 1259 | else |
1240 | { | 1260 | { |
@@ -1247,30 +1267,6 @@ public sealed class BSPrim : PhysicsActor | |||
1247 | } | 1267 | } |
1248 | } | 1268 | } |
1249 | 1269 | ||
1250 | // Create a linkset by creating a compound hull at the root prim that consists of all | ||
1251 | // the children. | ||
1252 | // NOTE: This does not allow proper collisions with the children prims so it is not a workable solution | ||
1253 | void CreateLinksetWithCompoundHull() | ||
1254 | { | ||
1255 | // If I am the root prim of a linkset, replace my physical shape with all the | ||
1256 | // pieces of the children. | ||
1257 | // All of the children should have called CreateGeom so they have a hull | ||
1258 | // in the physics engine already. Here we pull together all of those hulls | ||
1259 | // into one shape. | ||
1260 | int totalPrimsInLinkset = _childrenPrims.Count + 1; | ||
1261 | // m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, totalPrimsInLinkset); | ||
1262 | ShapeData[] shapes = new ShapeData[totalPrimsInLinkset]; | ||
1263 | FillShapeInfo(out shapes[0]); | ||
1264 | int ii = 1; | ||
1265 | foreach (BSPrim prim in _childrenPrims) | ||
1266 | { | ||
1267 | // m_log.DebugFormat("{0}: CreateLinkset: adding prim {1}", LogHeader, prim.LocalID); | ||
1268 | prim.FillShapeInfo(out shapes[ii]); | ||
1269 | ii++; | ||
1270 | } | ||
1271 | BulletSimAPI.CreateLinkset(_scene.WorldID, totalPrimsInLinkset, shapes); | ||
1272 | } | ||
1273 | |||
1274 | // Copy prim's info into the BulletSim shape description structure | 1270 | // Copy prim's info into the BulletSim shape description structure |
1275 | public void FillShapeInfo(out ShapeData shape) | 1271 | public void FillShapeInfo(out ShapeData shape) |
1276 | { | 1272 | { |
@@ -1280,7 +1276,7 @@ public sealed class BSPrim : PhysicsActor | |||
1280 | shape.Rotation = _orientation; | 1276 | shape.Rotation = _orientation; |
1281 | shape.Velocity = _velocity; | 1277 | shape.Velocity = _velocity; |
1282 | shape.Scale = _scale; | 1278 | shape.Scale = _scale; |
1283 | shape.Mass = _isPhysical ? _mass : 0f; | 1279 | shape.Mass = Mass; |
1284 | shape.Buoyancy = _buoyancy; | 1280 | shape.Buoyancy = _buoyancy; |
1285 | shape.HullKey = _hullKey; | 1281 | shape.HullKey = _hullKey; |
1286 | shape.MeshKey = _meshKey; | 1282 | shape.MeshKey = _meshKey; |
@@ -1290,45 +1286,73 @@ public sealed class BSPrim : PhysicsActor | |||
1290 | shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; | 1286 | shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; |
1291 | } | 1287 | } |
1292 | 1288 | ||
1289 | #region Linkset creation and destruction | ||
1290 | |||
1293 | // Create the linkset by putting constraints between the objects of the set so they cannot move | 1291 | // Create the linkset by putting constraints between the objects of the set so they cannot move |
1294 | // relative to each other. | 1292 | // relative to each other. |
1295 | // TODO: make this more effeicient: a large linkset gets rebuilt over and over and prims are added | 1293 | void CreateLinkset() |
1296 | void CreateLinksetWithConstraints() | ||
1297 | { | 1294 | { |
1298 | DebugLog("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1); | 1295 | DebugLog("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1); |
1299 | 1296 | ||
1300 | // remove any constraints that might be in place | 1297 | // remove any constraints that might be in place |
1301 | foreach (BSPrim prim in _childrenPrims) | 1298 | DebugLog("{0}: CreateLinkset: RemoveConstraints between me and any children", LogHeader, LocalID); |
1302 | { | 1299 | BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); |
1303 | DebugLog("{0}: CreateLinkset: RemoveConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID); | 1300 | |
1304 | BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, prim.LocalID); | ||
1305 | } | ||
1306 | // create constraints between the root prim and each of the children | 1301 | // create constraints between the root prim and each of the children |
1307 | foreach (BSPrim prim in _childrenPrims) | 1302 | foreach (BSPrim prim in _childrenPrims) |
1308 | { | 1303 | { |
1309 | // Zero motion for children so they don't interpolate | 1304 | LinkAChildToMe(prim); |
1310 | prim.ZeroMotion(); | ||
1311 | |||
1312 | // relative position normalized to the root prim | ||
1313 | OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(this._orientation); | ||
1314 | OMV.Vector3 childRelativePosition = (prim._position - this._position) * invThisOrientation; | ||
1315 | |||
1316 | // relative rotation of the child to the parent | ||
1317 | OMV.Quaternion childRelativeRotation = invThisOrientation * prim._orientation; | ||
1318 | |||
1319 | // this is a constraint that allows no freedom of movement between the two objects | ||
1320 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | ||
1321 | DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID); | ||
1322 | BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID, | ||
1323 | childRelativePosition, | ||
1324 | childRelativeRotation, | ||
1325 | OMV.Vector3.Zero, | ||
1326 | OMV.Quaternion.Identity, | ||
1327 | OMV.Vector3.Zero, OMV.Vector3.Zero, | ||
1328 | OMV.Vector3.Zero, OMV.Vector3.Zero); | ||
1329 | } | 1305 | } |
1330 | } | 1306 | } |
1331 | 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 | |||
1332 | // Rebuild the geometry and object. | 1356 | // Rebuild the geometry and object. |
1333 | // This is called when the shape changes so we need to recreate the mesh/hull. | 1357 | // This is called when the shape changes so we need to recreate the mesh/hull. |
1334 | // No locking here because this is done when the physics engine is not simulating | 1358 | // No locking here because this is done when the physics engine is not simulating |
@@ -1405,7 +1429,7 @@ public sealed class BSPrim : PhysicsActor | |||
1405 | // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. | 1429 | // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. |
1406 | 1430 | ||
1407 | // Updates only for individual prims and for the root object of a linkset. | 1431 | // Updates only for individual prims and for the root object of a linkset. |
1408 | if (this._parentPrim == null) | 1432 | if (_parentPrim == null) |
1409 | { | 1433 | { |
1410 | // Assign to the local variables so the normal set action does not happen | 1434 | // Assign to the local variables so the normal set action does not happen |
1411 | _position = entprop.Position; | 1435 | _position = entprop.Position; |