BulletSim: Rebuild physical body if physical shape changes for mesh and hull.

Properly rebuilds collision caches.
Release asset data fetched when building mesh or hulls.
user_profiles
Robert Adams 2013-05-02 10:06:12 -07:00
parent a9480aed85
commit d9c3947824
4 changed files with 73 additions and 24 deletions

View File

@ -596,6 +596,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
public override void Refresh() public override void Refresh()
{ {
// If asking for a refresh, reset the physical parameters before the next simulation step. // If asking for a refresh, reset the physical parameters before the next simulation step.
// Called whether active or not since the active state may be updated before the next step.
m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate() m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate()
{ {
SetPhysicalParameters(); SetPhysicalParameters();

View File

@ -767,7 +767,7 @@ public class BSPrim : BSPhysObject
if (!PhysBody.HasPhysicalBody) if (!PhysBody.HasPhysicalBody)
{ {
// This would only happen if updates are called for during initialization when the body is not set up yet. // This would only happen if updates are called for during initialization when the body is not set up yet.
DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID); // DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID);
return; return;
} }

View File

@ -227,16 +227,41 @@ public sealed class BSShapeCollection : IDisposable
if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects) if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
{ {
// Update prim.BSShape to reference a hull of this shape. // Update prim.BSShape to reference a hull of this shape.
BSShape potentialHull = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
// If the current shape is not what is on the prim at the moment, time to change.
if (!prim.PhysShape.HasPhysicalShape
|| potentialHull.ShapeType != prim.PhysShape.ShapeType
|| potentialHull.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
{
DereferenceExistingShape(prim, shapeCallback); DereferenceExistingShape(prim, shapeCallback);
prim.PhysShape = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim); prim.PhysShape = potentialHull;
ret = true;
}
else
{
potentialHull.Dereference(m_physicsScene);
}
if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
prim.LocalID, prim.PhysShape, prim.PhysShape.physShapeInfo.shapeKey.ToString("X")); prim.LocalID, prim.PhysShape, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"));
} }
else else
{ {
// Update prim.BSShape to reference a mesh of this shape. // Update prim.BSShape to reference a mesh of this shape.
BSShape potentialMesh = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
// If the current shape is not what is on the prim at the moment, time to change.
if (!prim.PhysShape.HasPhysicalShape
|| potentialMesh.ShapeType != prim.PhysShape.ShapeType
|| potentialMesh.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
{
DereferenceExistingShape(prim, shapeCallback); DereferenceExistingShape(prim, shapeCallback);
prim.PhysShape = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim); prim.PhysShape = potentialMesh;
ret = true;
}
else
{
// We don't need this reference to the mesh that is already being using.
potentialMesh.Dereference(m_physicsScene);
}
if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
prim.LocalID, prim.PhysShape, prim.PhysShape.physShapeInfo.shapeKey.ToString("X")); prim.LocalID, prim.PhysShape, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"));
} }
@ -320,7 +345,7 @@ public sealed class BSShapeCollection : IDisposable
if (prim.IsSolid) if (prim.IsSolid)
{ {
aBody = m_physicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation); aBody = m_physicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation);
if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,body={1}", prim.LocalID, aBody); if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,rigid,body={1}", prim.LocalID, aBody);
} }
else else
{ {

View File

@ -115,10 +115,15 @@ public abstract class BSShape
public override string ToString() public override string ToString()
{ {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
buff.Append("<t="); if (physShapeInfo == null)
buff.Append(ShapeType.ToString()); {
buff.Append(",p="); buff.Append(",noPhys");
buff.Append(AddrString); }
else
{
buff.Append(",phy=");
buff.Append(physShapeInfo.ToString());
}
buff.Append(",c="); buff.Append(",c=");
buff.Append(referenceCount.ToString()); buff.Append(referenceCount.ToString());
buff.Append(">"); buff.Append(">");
@ -184,21 +189,21 @@ public abstract class BSShape
BSPhysObject xprim = prim; BSPhysObject xprim = prim;
Util.FireAndForget(delegate Util.FireAndForget(delegate
{ {
physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,inFireAndForget", xprim.LocalID); // physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,inFireAndForget", xprim.LocalID);
RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod; RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod;
if (assetProvider != null) if (assetProvider != null)
{ {
BSPhysObject yprim = xprim; // probably not necessary, but, just in case. BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
{ {
physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,assetProviderCallback", xprim.LocalID); // physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,assetProviderCallback", xprim.LocalID);
bool assetFound = false; bool assetFound = false;
string mismatchIDs = String.Empty; // DEBUG DEBUG string mismatchIDs = String.Empty; // DEBUG DEBUG
if (asset != null && yprim.BaseShape.SculptEntry) if (asset != null && yprim.BaseShape.SculptEntry)
{ {
if (yprim.BaseShape.SculptTexture.ToString() == asset.ID) if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
{ {
yprim.BaseShape.SculptData = (byte[])asset.Data.Clone(); yprim.BaseShape.SculptData = asset.Data;
// This will cause the prim to see that the filler shape is not the right // This will cause the prim to see that the filler shape is not the right
// one and try again to build the object. // one and try again to build the object.
// No race condition with the normal shape setting since the rebuild is at taint time. // No race condition with the normal shape setting since the rebuild is at taint time.
@ -290,7 +295,7 @@ public class BSShapeNative : BSShape
{ {
if (physShapeInfo.HasPhysicalShape) if (physShapeInfo.HasPhysicalShape)
{ {
physicsScene.DetailLog("{0},BSShapeNative.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this); physicsScene.DetailLog("{0},BSShapeNative.Dereference,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo); physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo);
} }
physShapeInfo.Clear(); physShapeInfo.Clear();
@ -347,9 +352,8 @@ public class BSShapeMesh : BSShape
float lod; float lod;
System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
physicsScene.DetailLog("{0},BSShapeMesh,getReference,oldKey={1},newKey={2},size={3},lod={4}", physicsScene.DetailLog("{0},BSShapeMesh,getReference,newKey={1},size={2},lod={3}",
prim.LocalID, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"), prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod);
newMeshKey.ToString("X"), prim.Size, lod);
BSShapeMesh retMesh = null; BSShapeMesh retMesh = null;
lock (Meshes) lock (Meshes)
@ -389,6 +393,7 @@ public class BSShapeMesh : BSShape
lock (Meshes) lock (Meshes)
{ {
this.DecrementReference(); this.DecrementReference();
physicsScene.DetailLog("{0},BSShapeMesh.Dereference,shape={1}", BSScene.DetailLogZero, this);
// TODO: schedule aging and destruction of unused meshes. // TODO: schedule aging and destruction of unused meshes.
} }
} }
@ -425,6 +430,12 @@ public class BSShapeMesh : BSShape
if (meshData != null) if (meshData != null)
{ {
if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
{
// Release the fetched asset data once it has been used.
pbs.SculptData = new byte[0];
prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
}
int[] indices = meshData.getIndexListAsInt(); int[] indices = meshData.getIndexListAsInt();
int realIndicesIndex = indices.Length; int realIndicesIndex = indices.Length;
@ -462,8 +473,8 @@ public class BSShapeMesh : BSShape
} }
} }
} }
physicsScene.DetailLog("{0},BSShapeMesh.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}", physicsScene.DetailLog("{0},BSShapeMesh.CreatePhysicalMesh,key={1},origTri={2},realTri={3},numVerts={4}",
BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3); BSScene.DetailLogZero, newMeshKey.ToString("X"), indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
if (realIndicesIndex != 0) if (realIndicesIndex != 0)
{ {
@ -496,8 +507,8 @@ public class BSShapeHull : BSShape
float lod; float lod;
System.UInt64 newHullKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); System.UInt64 newHullKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
physicsScene.DetailLog("{0},BSShapeHull,getReference,oldKey={1},newKey={2},size={3},lod={4}", physicsScene.DetailLog("{0},BSShapeHull,getReference,newKey={1},size={2},lod={3}",
prim.LocalID, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"), newHullKey.ToString("X"), prim.Size, lod); prim.LocalID, newHullKey.ToString("X"), prim.Size, lod);
BSShapeHull retHull = null; BSShapeHull retHull = null;
lock (Hulls) lock (Hulls)
@ -537,6 +548,7 @@ public class BSShapeHull : BSShape
lock (Hulls) lock (Hulls)
{ {
this.DecrementReference(); this.DecrementReference();
physicsScene.DetailLog("{0},BSShapeHull.Dereference,shape={1}", BSScene.DetailLogZero, this);
// TODO: schedule aging and destruction of unused meshes. // TODO: schedule aging and destruction of unused meshes.
} }
} }
@ -549,6 +561,8 @@ public class BSShapeHull : BSShape
if (BSParam.ShouldUseBulletHACD) if (BSParam.ShouldUseBulletHACD)
{ {
// Build the hull shape from an existing mesh shape.
// The mesh should have already been created in Bullet.
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID); physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID);
BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim); BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim);
@ -568,18 +582,26 @@ public class BSShapeHull : BSShape
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape); physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms); newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms);
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape); physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
}
// Now done with the mesh shape. // Now done with the mesh shape.
meshShape.Dereference(physicsScene); meshShape.Dereference(physicsScene);
}
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape); physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
} }
if (!newShape.HasPhysicalShape) if (!newShape.HasPhysicalShape)
{ {
// Build a new hull in the physical world. // Build a new hull in the physical world using the C# HACD algorigthm.
// Pass true for physicalness as this prevents the creation of bounding box which is not needed // Pass true for physicalness as this prevents the creation of bounding box which is not needed
IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */); IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
if (meshData != null) if (meshData != null)
{ {
if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
{
// Release the fetched asset data once it has been used.
pbs.SculptData = new byte[0];
prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
}
int[] indices = meshData.getIndexListAsInt(); int[] indices = meshData.getIndexListAsInt();
List<OMV.Vector3> vertices = meshData.getVertexList(); List<OMV.Vector3> vertices = meshData.getVertexList();
@ -740,6 +762,7 @@ public class BSShapeCompound : BSShape
lock (physShapeInfo) lock (physShapeInfo)
{ {
this.DecrementReference(); this.DecrementReference();
physicsScene.DetailLog("{0},BSShapeCompound.Dereference,shape={1}", BSScene.DetailLogZero, this);
if (referenceCount <= 0) if (referenceCount <= 0)
{ {
if (!physicsScene.PE.IsCompound(physShapeInfo)) if (!physicsScene.PE.IsCompound(physShapeInfo))