aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
authorRobert Adams2013-01-31 15:52:50 -0800
committerRobert Adams2013-01-31 15:56:10 -0800
commit75a05c16c5c0ec0712f7f564b60530e0a3fd1c82 (patch)
treefc6700bc9c7b6e04ea0e6615b57b04ffc1fcb2cd /OpenSim/Region/Physics
parentBulletSim: make sure vehicle physical properties are set when going (diff)
downloadopensim-SC_OLD-75a05c16c5c0ec0712f7f564b60530e0a3fd1c82.zip
opensim-SC_OLD-75a05c16c5c0ec0712f7f564b60530e0a3fd1c82.tar.gz
opensim-SC_OLD-75a05c16c5c0ec0712f7f564b60530e0a3fd1c82.tar.bz2
opensim-SC_OLD-75a05c16c5c0ec0712f7f564b60530e0a3fd1c82.tar.xz
BulletSim: fix crash caused when linksets were rebuilt. A problem added
when individual child pos/rot changes were implementated a week or so ago. Remove some passing of inTaintTime flag when it was never false.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs48
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs16
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs114
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt4
5 files changed, 106 insertions, 80 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 73354bb..192bcb5 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -126,9 +126,9 @@ public sealed class BSCharacter : BSPhysObject
126 DetailLog("{0},BSCharacter.Destroy", LocalID); 126 DetailLog("{0},BSCharacter.Destroy", LocalID);
127 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() 127 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
128 { 128 {
129 PhysicsScene.Shapes.DereferenceBody(PhysBody, true /* inTaintTime */, null /* bodyCallback */); 129 PhysicsScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */);
130 PhysBody.Clear(); 130 PhysBody.Clear();
131 PhysicsScene.Shapes.DereferenceShape(PhysShape, true /* inTaintTime */, null /* bodyCallback */); 131 PhysicsScene.Shapes.DereferenceShape(PhysShape, null /* bodyCallback */);
132 PhysShape.Clear(); 132 PhysShape.Clear();
133 }); 133 });
134 } 134 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index 92f6ee2..6c6ca09 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -219,28 +219,45 @@ public sealed class BSLinksetCompound : BSLinkset
219 { 219 {
220 // Gather the child info. It might not be there if the linkset is in transition. 220 // Gather the child info. It might not be there if the linkset is in transition.
221 BSLinksetCompoundInfo lsi = updated.LinksetInfo as BSLinksetCompoundInfo; 221 BSLinksetCompoundInfo lsi = updated.LinksetInfo as BSLinksetCompoundInfo;
222
223 // The linksetInfo will need to be rebuilt either here or when the linkset is rebuilt
222 if (LinksetRoot.PhysShape.HasPhysicalShape && lsi != null) 224 if (LinksetRoot.PhysShape.HasPhysicalShape && lsi != null)
223 { 225 {
224 if (PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) 226 if (PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape))
225 { 227 {
226 BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, lsi.Index); 228 int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape);
227 if (linksetChildShape.HasPhysicalShape) 229 if (lsi.Index < numLinksetChildren)
228 { 230 {
229 // Compute the offset from the center-of-gravity 231 // It is possible that the linkset is still under construction and the child is not yet
230 BSLinksetCompoundInfo newLsi = new BSLinksetCompoundInfo(lsi.Index, LinksetRoot, updated, LinksetRoot.PositionDisplacement); 232 // inserted into the compound shape. A rebuild of the linkset in a pre-step action will
231 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, lsi.Index, 233 // build the whole thing with the new position or rotation.
232 newLsi.OffsetFromCenterOfMass, 234 // This must be checked for because Bullet references the child array but does no validity
233 newLsi.OffsetRot, 235 // checking of the child index passed.
234 true /* shouldRecalculateLocalAabb */); 236 BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, lsi.Index);
235 DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}", 237 if (linksetChildShape.HasPhysicalShape)
236 updated.LocalID, whichUpdated, newLsi); 238 {
237 updated.LinksetInfo = newLsi; 239 // Compute the offset from the center-of-gravity
238 updatedChild = true; 240 BSLinksetCompoundInfo newLsi = new BSLinksetCompoundInfo(lsi.Index, LinksetRoot, updated, LinksetRoot.PositionDisplacement);
241 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, lsi.Index,
242 newLsi.OffsetFromCenterOfMass,
243 newLsi.OffsetRot,
244 true /* shouldRecalculateLocalAabb */);
245 updated.LinksetInfo = newLsi;
246 updatedChild = true;
247 DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}",
248 updated.LocalID, whichUpdated, newLsi);
249 }
250 else // DEBUG DEBUG
251 { // DEBUG DEBUG
252 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}",
253 updated.LocalID, linksetChildShape);
254 } // DEBUG DEBUG
239 } 255 }
240 else // DEBUG DEBUG 256 else // DEBUG DEBUG
241 { // DEBUG DEBUG 257 { // DEBUG DEBUG
242 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}", 258 // the child is not yet in the compound shape. This is non-fatal.
243 updated.LocalID, linksetChildShape); 259 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}",
260 updated.LocalID, numLinksetChildren, lsi.Index);
244 } // DEBUG DEBUG 261 } // DEBUG DEBUG
245 } 262 }
246 else // DEBUG DEBUG 263 else // DEBUG DEBUG
@@ -256,6 +273,9 @@ public sealed class BSLinksetCompound : BSLinkset
256 if (!updatedChild) 273 if (!updatedChild)
257 { 274 {
258 // If couldn't do the individual child, the linkset needs a rebuild to incorporate the new child info. 275 // If couldn't do the individual child, the linkset needs a rebuild to incorporate the new child info.
276 // Note that there are several ways through this code that will not update the child that can
277 // occur if the linkset is being rebuilt. In this case, scheduling a rebuild is a NOOP since
278 // there will already be a rebuild scheduled.
259 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild.schedulingRebuild,whichUpdated={1}", 279 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild.schedulingRebuild,whichUpdated={1}",
260 updated.LocalID, whichUpdated); 280 updated.LocalID, whichUpdated);
261 updated.LinksetInfo = null; // setting to 'null' causes relative position to be recomputed. 281 updated.LinksetInfo = null; // setting to 'null' causes relative position to be recomputed.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 0b81122..54bf063 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -146,9 +146,9 @@ public sealed class BSPrim : BSPhysObject
146 { 146 {
147 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 147 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
148 // If there are physical body and shape, release my use of same. 148 // If there are physical body and shape, release my use of same.
149 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); 149 PhysicsScene.Shapes.DereferenceBody(PhysBody, null);
150 PhysBody.Clear(); 150 PhysBody.Clear();
151 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); 151 PhysicsScene.Shapes.DereferenceShape(PhysShape, null);
152 PhysShape.Clear(); 152 PhysShape.Clear();
153 }); 153 });
154 } 154 }
@@ -181,11 +181,19 @@ public sealed class BSPrim : BSPhysObject
181 181
182 public override bool ForceBodyShapeRebuild(bool inTaintTime) 182 public override bool ForceBodyShapeRebuild(bool inTaintTime)
183 { 183 {
184 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate() 184 if (inTaintTime)
185 { 185 {
186 _mass = CalculateMass(); // changing the shape changes the mass 186 _mass = CalculateMass(); // changing the shape changes the mass
187 CreateGeomAndObject(true); 187 CreateGeomAndObject(true);
188 }); 188 }
189 else
190 {
191 PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate()
192 {
193 _mass = CalculateMass(); // changing the shape changes the mass
194 CreateGeomAndObject(true);
195 });
196 }
189 return true; 197 return true;
190 } 198 }
191 public override bool Grabbed { 199 public override bool Grabbed {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index e2daa72..9febd90 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -133,48 +133,44 @@ public sealed class BSShapeCollection : IDisposable
133 // Track another user of a body. 133 // Track another user of a body.
134 // We presume the caller has allocated the body. 134 // We presume the caller has allocated the body.
135 // Bodies only have one user so the body is just put into the world if not already there. 135 // Bodies only have one user so the body is just put into the world if not already there.
136 public void ReferenceBody(BulletBody body, bool inTaintTime) 136 private void ReferenceBody(BulletBody body)
137 { 137 {
138 lock (m_collectionActivityLock) 138 lock (m_collectionActivityLock)
139 { 139 {
140 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); 140 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
141 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() 141 if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
142 { 142 {
143 if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body)) 143 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body);
144 { 144 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
145 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body); 145 }
146 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
147 }
148 });
149 } 146 }
150 } 147 }
151 148
152 // Release the usage of a body. 149 // Release the usage of a body.
153 // Called when releasing use of a BSBody. BSShape is handled separately. 150 // Called when releasing use of a BSBody. BSShape is handled separately.
154 public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) 151 // Called in taint time.
152 public void DereferenceBody(BulletBody body, BodyDestructionCallback bodyCallback )
155 { 153 {
156 if (!body.HasPhysicalBody) 154 if (!body.HasPhysicalBody)
157 return; 155 return;
158 156
157 PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody");
158
159 lock (m_collectionActivityLock) 159 lock (m_collectionActivityLock)
160 { 160 {
161 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() 161 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body);
162 { 162 // If the caller needs to know the old body is going away, pass the event up.
163 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", 163 if (bodyCallback != null) bodyCallback(body);
164 body.ID, body, inTaintTime);
165 // If the caller needs to know the old body is going away, pass the event up.
166 if (bodyCallback != null) bodyCallback(body);
167 164
168 if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body)) 165 if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
169 { 166 {
170 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body); 167 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body);
171 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); 168 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
172 } 169 }
173 170
174 // Zero any reference to the shape so it is not freed when the body is deleted. 171 // Zero any reference to the shape so it is not freed when the body is deleted.
175 PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null); 172 PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null);
176 PhysicsScene.PE.DestroyObject(PhysicsScene.World, body); 173 PhysicsScene.PE.DestroyObject(PhysicsScene.World, body);
177 });
178 } 174 }
179 } 175 }
180 176
@@ -245,44 +241,43 @@ public sealed class BSShapeCollection : IDisposable
245 } 241 }
246 242
247 // Release the usage of a shape. 243 // Release the usage of a shape.
248 public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) 244 public void DereferenceShape(BulletShape shape, ShapeDestructionCallback shapeCallback)
249 { 245 {
250 if (!shape.HasPhysicalShape) 246 if (!shape.HasPhysicalShape)
251 return; 247 return;
252 248
253 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() 249 PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceShape");
250
251 if (shape.HasPhysicalShape)
254 { 252 {
255 if (shape.HasPhysicalShape) 253 if (shape.isNativeShape)
256 { 254 {
257 if (shape.isNativeShape) 255 // Native shapes are not tracked and are released immediately
258 { 256 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1}",
259 // Native shapes are not tracked and are released immediately 257 BSScene.DetailLogZero, shape.AddrString);
260 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", 258 if (shapeCallback != null) shapeCallback(shape);
261 BSScene.DetailLogZero, shape.AddrString, inTaintTime); 259 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
262 if (shapeCallback != null) shapeCallback(shape); 260 }
263 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape); 261 else
264 } 262 {
265 else 263 switch (shape.type)
266 { 264 {
267 switch (shape.type) 265 case BSPhysicsShapeType.SHAPE_HULL:
268 { 266 DereferenceHull(shape, shapeCallback);
269 case BSPhysicsShapeType.SHAPE_HULL: 267 break;
270 DereferenceHull(shape, shapeCallback); 268 case BSPhysicsShapeType.SHAPE_MESH:
271 break; 269 DereferenceMesh(shape, shapeCallback);
272 case BSPhysicsShapeType.SHAPE_MESH: 270 break;
273 DereferenceMesh(shape, shapeCallback); 271 case BSPhysicsShapeType.SHAPE_COMPOUND:
274 break; 272 DereferenceCompound(shape, shapeCallback);
275 case BSPhysicsShapeType.SHAPE_COMPOUND: 273 break;
276 DereferenceCompound(shape, shapeCallback); 274 case BSPhysicsShapeType.SHAPE_UNKNOWN:
277 break; 275 break;
278 case BSPhysicsShapeType.SHAPE_UNKNOWN: 276 default:
279 break; 277 break;
280 default:
281 break;
282 }
283 } 278 }
284 } 279 }
285 }); 280 }
286 } 281 }
287 282
288 // Count down the reference count for a mesh shape 283 // Count down the reference count for a mesh shape
@@ -393,7 +388,7 @@ public sealed class BSShapeCollection : IDisposable
393 388
394 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN) 389 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
395 { 390 {
396 DereferenceShape(shapeInfo, true, null); 391 DereferenceShape(shapeInfo, null);
397 } 392 }
398 else 393 else
399 { 394 {
@@ -543,7 +538,7 @@ public sealed class BSShapeCollection : IDisposable
543 ShapeDestructionCallback shapeCallback) 538 ShapeDestructionCallback shapeCallback)
544 { 539 {
545 // release any previous shape 540 // release any previous shape
546 DereferenceShape(prim.PhysShape, true, shapeCallback); 541 DereferenceShape(prim.PhysShape, shapeCallback);
547 542
548 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); 543 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
549 544
@@ -611,7 +606,7 @@ public sealed class BSShapeCollection : IDisposable
611 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); 606 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
612 607
613 // Since we're recreating new, get rid of the reference to the previous shape 608 // Since we're recreating new, get rid of the reference to the previous shape
614 DereferenceShape(prim.PhysShape, true, shapeCallback); 609 DereferenceShape(prim.PhysShape, shapeCallback);
615 610
616 newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod); 611 newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod);
617 // Take evasive action if the mesh was not constructed. 612 // Take evasive action if the mesh was not constructed.
@@ -682,7 +677,7 @@ public sealed class BSShapeCollection : IDisposable
682 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); 677 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
683 678
684 // Remove usage of the previous shape. 679 // Remove usage of the previous shape.
685 DereferenceShape(prim.PhysShape, true, shapeCallback); 680 DereferenceShape(prim.PhysShape, shapeCallback);
686 681
687 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); 682 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
688 newShape = VerifyMeshCreated(newShape, prim); 683 newShape = VerifyMeshCreated(newShape, prim);
@@ -817,7 +812,6 @@ public sealed class BSShapeCollection : IDisposable
817 // Don't need to do this as the shape is freed when the new root shape is created below. 812 // Don't need to do this as the shape is freed when the new root shape is created below.
818 // DereferenceShape(prim.PhysShape, true, shapeCallback); 813 // DereferenceShape(prim.PhysShape, true, shapeCallback);
819 814
820
821 BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false); 815 BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false);
822 816
823 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. 817 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
@@ -956,7 +950,7 @@ public sealed class BSShapeCollection : IDisposable
956 if (mustRebuild || forceRebuild) 950 if (mustRebuild || forceRebuild)
957 { 951 {
958 // Free any old body 952 // Free any old body
959 DereferenceBody(prim.PhysBody, true, bodyCallback); 953 DereferenceBody(prim.PhysBody, bodyCallback);
960 954
961 BulletBody aBody; 955 BulletBody aBody;
962 if (prim.IsSolid) 956 if (prim.IsSolid)
@@ -970,7 +964,7 @@ public sealed class BSShapeCollection : IDisposable
970 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody); 964 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody);
971 } 965 }
972 966
973 ReferenceBody(aBody, true); 967 ReferenceBody(aBody);
974 968
975 prim.PhysBody = aBody; 969 prim.PhysBody = aBody;
976 970
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index d574a49..7dfdec1 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -65,6 +65,10 @@ Vehicle attributes are not restored when a vehicle is rezzed on region creation
65 65
66GENERAL TODO LIST: 66GENERAL TODO LIST:
67================================================= 67=================================================
68Collisions are inconsistant: arrows are supposed to hit and report collision. Often don't.
69 If arrow show at prim, collision reported about 1/3 of time. If collision reported,
70 both arrow and prim report it. The arrow bounces off the prim 9 out of 10 times.
71 Shooting 5m sphere "arrows" at 60m/s.
68llMoveToTarget objects are not effected by gravity until target is removed. 72llMoveToTarget objects are not effected by gravity until target is removed.
69Compute CCD parameters based on body size 73Compute CCD parameters based on body size
70Can solver iterations be changed per body/shape? Can be for constraints but what 74Can solver iterations be changed per body/shape? Can be for constraints but what