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()
{
// 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()
{
SetPhysicalParameters();

View File

@ -767,7 +767,7 @@ public class BSPrim : BSPhysObject
if (!PhysBody.HasPhysicalBody)
{
// 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;
}

View File

@ -227,16 +227,41 @@ public sealed class BSShapeCollection : IDisposable
if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
{
// Update prim.BSShape to reference a hull of this shape.
DereferenceExistingShape(prim, shapeCallback);
prim.PhysShape = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
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);
prim.PhysShape = potentialHull;
ret = true;
}
else
{
potentialHull.Dereference(m_physicsScene);
}
if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
prim.LocalID, prim.PhysShape, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"));
}
else
{
// Update prim.BSShape to reference a mesh of this shape.
DereferenceExistingShape(prim, shapeCallback);
prim.PhysShape = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
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);
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}",
prim.LocalID, prim.PhysShape, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"));
}
@ -320,7 +345,7 @@ public sealed class BSShapeCollection : IDisposable
if (prim.IsSolid)
{
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
{

View File

@ -115,10 +115,15 @@ public abstract class BSShape
public override string ToString()
{
StringBuilder buff = new StringBuilder();
buff.Append("<t=");
buff.Append(ShapeType.ToString());
buff.Append(",p=");
buff.Append(AddrString);
if (physShapeInfo == null)
{
buff.Append(",noPhys");
}
else
{
buff.Append(",phy=");
buff.Append(physShapeInfo.ToString());
}
buff.Append(",c=");
buff.Append(referenceCount.ToString());
buff.Append(">");
@ -184,21 +189,21 @@ public abstract class BSShape
BSPhysObject xprim = prim;
Util.FireAndForget(delegate
{
physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,inFireAndForget", xprim.LocalID);
// physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,inFireAndForget", xprim.LocalID);
RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod;
if (assetProvider != null)
{
BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
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;
string mismatchIDs = String.Empty; // DEBUG DEBUG
if (asset != null && yprim.BaseShape.SculptEntry)
{
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
// one and try again to build the object.
// 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)
{
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);
}
physShapeInfo.Clear();
@ -347,9 +352,8 @@ public class BSShapeMesh : BSShape
float 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}",
prim.LocalID, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"),
newMeshKey.ToString("X"), prim.Size, lod);
physicsScene.DetailLog("{0},BSShapeMesh,getReference,newKey={1},size={2},lod={3}",
prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod);
BSShapeMesh retMesh = null;
lock (Meshes)
@ -389,6 +393,7 @@ public class BSShapeMesh : BSShape
lock (Meshes)
{
this.DecrementReference();
physicsScene.DetailLog("{0},BSShapeMesh.Dereference,shape={1}", BSScene.DetailLogZero, this);
// TODO: schedule aging and destruction of unused meshes.
}
}
@ -425,6 +430,12 @@ public class BSShapeMesh : BSShape
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 realIndicesIndex = indices.Length;
@ -462,8 +473,8 @@ public class BSShapeMesh : BSShape
}
}
}
physicsScene.DetailLog("{0},BSShapeMesh.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}",
BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
physicsScene.DetailLog("{0},BSShapeMesh.CreatePhysicalMesh,key={1},origTri={2},realTri={3},numVerts={4}",
BSScene.DetailLogZero, newMeshKey.ToString("X"), indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
if (realIndicesIndex != 0)
{
@ -496,8 +507,8 @@ public class BSShapeHull : BSShape
float 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}",
prim.LocalID, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"), newHullKey.ToString("X"), prim.Size, lod);
physicsScene.DetailLog("{0},BSShapeHull,getReference,newKey={1},size={2},lod={3}",
prim.LocalID, newHullKey.ToString("X"), prim.Size, lod);
BSShapeHull retHull = null;
lock (Hulls)
@ -537,6 +548,7 @@ public class BSShapeHull : BSShape
lock (Hulls)
{
this.DecrementReference();
physicsScene.DetailLog("{0},BSShapeHull.Dereference,shape={1}", BSScene.DetailLogZero, this);
// TODO: schedule aging and destruction of unused meshes.
}
}
@ -549,6 +561,8 @@ public class BSShapeHull : BSShape
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);
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);
newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms);
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
// Now done with the mesh shape.
meshShape.Dereference(physicsScene);
}
// Now done with the mesh shape.
meshShape.Dereference(physicsScene);
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, 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
IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
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();
List<OMV.Vector3> vertices = meshData.getVertexList();
@ -740,6 +762,7 @@ public class BSShapeCompound : BSShape
lock (physShapeInfo)
{
this.DecrementReference();
physicsScene.DetailLog("{0},BSShapeCompound.Dereference,shape={1}", BSScene.DetailLogZero, this);
if (referenceCount <= 0)
{
if (!physicsScene.PE.IsCompound(physShapeInfo))