BulletSim: partial addition of BSShape class code preparing for
different physical mesh representations (simplified convex meshes) and avatar mesh.user_profiles
parent
e324f6f3f0
commit
c22a2ab7d2
|
@ -612,7 +612,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
|
||||
newShape = CreatePhysicalMesh(prim, newMeshKey, prim.BaseShape, prim.Size, lod);
|
||||
// Take evasive action if the mesh was not constructed.
|
||||
newShape = VerifyMeshCreated(newShape, prim);
|
||||
newShape = VerifyMeshCreated(PhysicsScene, newShape, prim);
|
||||
|
||||
ReferenceShape(newShape);
|
||||
|
||||
|
@ -719,7 +719,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
|
||||
newShape = CreatePhysicalHull(prim, newHullKey, prim.BaseShape, prim.Size, lod);
|
||||
// It might not have been created if we're waiting for an asset.
|
||||
newShape = VerifyMeshCreated(newShape, prim);
|
||||
newShape = VerifyMeshCreated(PhysicsScene, newShape, prim);
|
||||
|
||||
ReferenceShape(newShape);
|
||||
|
||||
|
@ -923,7 +923,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
|
||||
// Create a hash of all the shape parameters to be used as a key
|
||||
// for this particular shape.
|
||||
private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
|
||||
public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
|
||||
{
|
||||
// level of detail based on size and type of the object
|
||||
float lod = BSParam.MeshLOD;
|
||||
|
@ -944,7 +944,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
return pbs.GetMeshKey(size, lod);
|
||||
}
|
||||
// For those who don't want the LOD
|
||||
private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs)
|
||||
public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs)
|
||||
{
|
||||
float lod;
|
||||
return ComputeShapeKey(size, pbs, out lod);
|
||||
|
@ -957,7 +957,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
// us to not loop forever.
|
||||
// Called after creating a physical mesh or hull. If the physical shape was created,
|
||||
// just return.
|
||||
private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim)
|
||||
public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim)
|
||||
{
|
||||
// If the shape was successfully created, nothing more to do
|
||||
if (newShape.HasPhysicalShape)
|
||||
|
@ -969,7 +969,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
|
||||
{
|
||||
prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
|
||||
PhysicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
|
||||
physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
|
||||
LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
|
||||
}
|
||||
else
|
||||
|
@ -981,14 +981,14 @@ public sealed class BSShapeCollection : IDisposable
|
|||
&& prim.BaseShape.SculptTexture != OMV.UUID.Zero
|
||||
)
|
||||
{
|
||||
DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
|
||||
physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
|
||||
// Multiple requestors will know we're waiting for this asset
|
||||
prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
|
||||
|
||||
BSPhysObject xprim = prim;
|
||||
Util.FireAndForget(delegate
|
||||
{
|
||||
RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
|
||||
RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod;
|
||||
if (assetProvider != null)
|
||||
{
|
||||
BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
|
||||
|
@ -1016,7 +1016,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
|
||||
else
|
||||
yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
|
||||
DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
|
||||
physicsScene.DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
|
||||
yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
|
||||
|
||||
});
|
||||
|
@ -1024,8 +1024,8 @@ public sealed class BSShapeCollection : IDisposable
|
|||
else
|
||||
{
|
||||
xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
|
||||
PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
|
||||
LogHeader, PhysicsScene.Name);
|
||||
physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
|
||||
LogHeader, physicsScene.Name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1033,15 +1033,15 @@ public sealed class BSShapeCollection : IDisposable
|
|||
{
|
||||
if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
|
||||
{
|
||||
PhysicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
|
||||
physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
|
||||
LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// While we wait for the mesh defining asset to be loaded, stick in a simple box for the object.
|
||||
BulletShape fillinShape = BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
|
||||
DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID);
|
||||
BulletShape fillinShape = physicsScene.Shapes.BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
|
||||
physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID);
|
||||
|
||||
return fillinShape;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,9 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
|
||||
using OMV = OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
|
@ -37,11 +40,19 @@ public abstract class BSShape
|
|||
{
|
||||
public int referenceCount { get; set; }
|
||||
public DateTime lastReferenced { get; set; }
|
||||
public BulletShape physShapeInfo { get; set; }
|
||||
|
||||
public BSShape()
|
||||
{
|
||||
referenceCount = 0;
|
||||
lastReferenced = DateTime.Now;
|
||||
physShapeInfo = new BulletShape();
|
||||
}
|
||||
public BSShape(BulletShape pShape)
|
||||
{
|
||||
referenceCount = 0;
|
||||
lastReferenced = DateTime.Now;
|
||||
physShapeInfo = pShape;
|
||||
}
|
||||
|
||||
// Get a reference to a physical shape. Create if it doesn't exist
|
||||
|
@ -79,21 +90,30 @@ public abstract class BSShape
|
|||
|
||||
return ret;
|
||||
}
|
||||
public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
|
||||
private static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
|
||||
{
|
||||
BSShapeMesh.GetReference(physicsScene, forceRebuild, prim);
|
||||
BSShapeHull.GetReference(physicsScene, forceRebuild, prim);
|
||||
return null;
|
||||
}
|
||||
public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
|
||||
|
||||
// Called when this shape is being used again.
|
||||
public virtual void IncrementReference()
|
||||
{
|
||||
return null;
|
||||
referenceCount++;
|
||||
lastReferenced = DateTime.Now;
|
||||
}
|
||||
|
||||
// Called when this shape is being used again.
|
||||
public virtual void DecrementReference()
|
||||
{
|
||||
referenceCount--;
|
||||
lastReferenced = DateTime.Now;
|
||||
}
|
||||
|
||||
// Release the use of a physical shape.
|
||||
public abstract void Dereference(BSScene physicsScene);
|
||||
|
||||
// All shapes have a static call to get a reference to the physical shape
|
||||
// protected abstract static BSShape GetReference();
|
||||
|
||||
// Returns a string for debugging that uniquily identifies the memory used by this instance
|
||||
public virtual string AddrString
|
||||
{
|
||||
|
@ -112,6 +132,7 @@ public abstract class BSShape
|
|||
}
|
||||
}
|
||||
|
||||
// ============================================================================================================
|
||||
public class BSShapeNull : BSShape
|
||||
{
|
||||
public BSShapeNull() : base()
|
||||
|
@ -121,23 +142,39 @@ public class BSShapeNull : BSShape
|
|||
public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ }
|
||||
}
|
||||
|
||||
// ============================================================================================================
|
||||
public class BSShapeNative : BSShape
|
||||
{
|
||||
private static string LogHeader = "[BULLETSIM SHAPE NATIVE]";
|
||||
public BSShapeNative() : base()
|
||||
public BSShapeNative(BulletShape pShape) : base(pShape)
|
||||
{
|
||||
}
|
||||
public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim,
|
||||
BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
|
||||
{
|
||||
// Native shapes are not shared and are always built anew.
|
||||
//return new BSShapeNative(physicsScene, prim, shapeType, shapeKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
private BSShapeNative(BSScene physicsScene, BSPhysObject prim,
|
||||
BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
|
||||
public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim,
|
||||
BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
|
||||
{
|
||||
// Native shapes are not shared and are always built anew.
|
||||
return new BSShapeNative(CreatePhysicalNativeShape(physicsScene, prim, shapeType, shapeKey));
|
||||
}
|
||||
|
||||
// Make this reference to the physical shape go away since native shapes are not shared.
|
||||
public override void Dereference(BSScene physicsScene)
|
||||
{
|
||||
// Native shapes are not tracked and are released immediately
|
||||
if (physShapeInfo.HasPhysicalShape)
|
||||
{
|
||||
physicsScene.DetailLog("{0},BSShapeNative.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
|
||||
physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo);
|
||||
}
|
||||
physShapeInfo.Clear();
|
||||
// Garbage collection will free up this instance.
|
||||
}
|
||||
|
||||
private static BulletShape CreatePhysicalNativeShape(BSScene physicsScene, BSPhysObject prim,
|
||||
BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
|
||||
{
|
||||
BulletShape newShape;
|
||||
|
||||
ShapeData nativeShapeData = new ShapeData();
|
||||
nativeShapeData.Type = shapeType;
|
||||
nativeShapeData.ID = prim.LocalID;
|
||||
|
@ -146,63 +183,164 @@ public class BSShapeNative : BSShape
|
|||
nativeShapeData.MeshKey = (ulong)shapeKey;
|
||||
nativeShapeData.HullKey = (ulong)shapeKey;
|
||||
|
||||
|
||||
/*
|
||||
if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
|
||||
{
|
||||
ptr = PhysicsScene.PE.BuildCapsuleShape(physicsScene.World, 1f, 1f, prim.Scale);
|
||||
physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
|
||||
newShape = physicsScene.PE.BuildCapsuleShape(physicsScene.World, 1f, 1f, prim.Scale);
|
||||
physicsScene.DetailLog("{0},BSShapeNative,capsule,scale={1}", prim.LocalID, prim.Scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = PhysicsScene.PE.BuildNativeShape(physicsScene.World, nativeShapeData);
|
||||
newShape = physicsScene.PE.BuildNativeShape(physicsScene.World, nativeShapeData);
|
||||
}
|
||||
if (ptr == IntPtr.Zero)
|
||||
if (!newShape.HasPhysicalShape)
|
||||
{
|
||||
physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
|
||||
LogHeader, prim.LocalID, shapeType);
|
||||
}
|
||||
type = shapeType;
|
||||
key = (UInt64)shapeKey;
|
||||
*/
|
||||
}
|
||||
// Make this reference to the physical shape go away since native shapes are not shared.
|
||||
public override void Dereference(BSScene physicsScene)
|
||||
{
|
||||
/*
|
||||
// Native shapes are not tracked and are released immediately
|
||||
physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
|
||||
PhysicsScene.PE.DeleteCollisionShape(physicsScene.World, this);
|
||||
ptr = IntPtr.Zero;
|
||||
// Garbage collection will free up this instance.
|
||||
*/
|
||||
newShape.type = shapeType;
|
||||
newShape.isNativeShape = true;
|
||||
newShape.shapeKey = (UInt64)shapeKey;
|
||||
return newShape;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ============================================================================================================
|
||||
public class BSShapeMesh : BSShape
|
||||
{
|
||||
private static string LogHeader = "[BULLETSIM SHAPE MESH]";
|
||||
private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>();
|
||||
|
||||
public BSShapeMesh() : base()
|
||||
public BSShapeMesh(BulletShape pShape) : base(pShape)
|
||||
{
|
||||
}
|
||||
public static BSShape GetReference() { return new BSShapeNull(); }
|
||||
public override void Dereference(BSScene physicsScene) { }
|
||||
public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
|
||||
{
|
||||
float lod;
|
||||
System.UInt64 newMeshKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
|
||||
|
||||
physicsScene.DetailLog("{0},BSShapeMesh,create,oldKey={1},newKey={2},size={3},lod={4}",
|
||||
prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod);
|
||||
|
||||
BSShapeMesh retMesh;
|
||||
lock (Meshes)
|
||||
{
|
||||
if (Meshes.TryGetValue(newMeshKey, out retMesh))
|
||||
{
|
||||
// The mesh has already been created. Return a new reference to same.
|
||||
retMesh.IncrementReference();
|
||||
}
|
||||
else
|
||||
{
|
||||
// An instance of this mesh has not been created. Build and remember same.
|
||||
BulletShape newShape = CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);
|
||||
// Take evasive action if the mesh was not constructed.
|
||||
newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim);
|
||||
|
||||
retMesh = new BSShapeMesh(newShape);
|
||||
|
||||
Meshes.Add(newMeshKey, retMesh);
|
||||
}
|
||||
}
|
||||
return retMesh;
|
||||
}
|
||||
public override void Dereference(BSScene physicsScene)
|
||||
{
|
||||
lock (Meshes)
|
||||
{
|
||||
this.DecrementReference();
|
||||
// TODO: schedule aging and destruction of unused meshes.
|
||||
}
|
||||
}
|
||||
|
||||
private static BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
|
||||
PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
|
||||
{
|
||||
BulletShape newShape = null;
|
||||
|
||||
IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
|
||||
false, // say it is not physical so a bounding box is not built
|
||||
false // do not cache the mesh and do not use previously built versions
|
||||
);
|
||||
|
||||
if (meshData != null)
|
||||
{
|
||||
|
||||
int[] indices = meshData.getIndexListAsInt();
|
||||
int realIndicesIndex = indices.Length;
|
||||
float[] verticesAsFloats = meshData.getVertexListAsFloat();
|
||||
|
||||
if (BSParam.ShouldRemoveZeroWidthTriangles)
|
||||
{
|
||||
// Remove degenerate triangles. These are triangles with two of the vertices
|
||||
// are the same. This is complicated by the problem that vertices are not
|
||||
// made unique in sculpties so we have to compare the values in the vertex.
|
||||
realIndicesIndex = 0;
|
||||
for (int tri = 0; tri < indices.Length; tri += 3)
|
||||
{
|
||||
// Compute displacements into vertex array for each vertex of the triangle
|
||||
int v1 = indices[tri + 0] * 3;
|
||||
int v2 = indices[tri + 1] * 3;
|
||||
int v3 = indices[tri + 2] * 3;
|
||||
// Check to see if any two of the vertices are the same
|
||||
if (!( ( verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0]
|
||||
&& verticesAsFloats[v1 + 1] == verticesAsFloats[v2 + 1]
|
||||
&& verticesAsFloats[v1 + 2] == verticesAsFloats[v2 + 2])
|
||||
|| ( verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0]
|
||||
&& verticesAsFloats[v2 + 1] == verticesAsFloats[v3 + 1]
|
||||
&& verticesAsFloats[v2 + 2] == verticesAsFloats[v3 + 2])
|
||||
|| ( verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0]
|
||||
&& verticesAsFloats[v1 + 1] == verticesAsFloats[v3 + 1]
|
||||
&& verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]) )
|
||||
)
|
||||
{
|
||||
// None of the vertices of the triangles are the same. This is a good triangle;
|
||||
indices[realIndicesIndex + 0] = indices[tri + 0];
|
||||
indices[realIndicesIndex + 1] = indices[tri + 1];
|
||||
indices[realIndicesIndex + 2] = indices[tri + 2];
|
||||
realIndicesIndex += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}",
|
||||
BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
|
||||
|
||||
if (realIndicesIndex != 0)
|
||||
{
|
||||
newShape = physicsScene.PE.CreateMeshShape(physicsScene.World,
|
||||
realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
|
||||
}
|
||||
else
|
||||
{
|
||||
physicsScene.Logger.DebugFormat("{0} All mesh triangles degenerate. Prim {1} at {2} in {3}",
|
||||
LogHeader, prim.PhysObjectName, prim.RawPosition, physicsScene.Name);
|
||||
}
|
||||
}
|
||||
newShape.shapeKey = newMeshKey;
|
||||
|
||||
return newShape;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================================================
|
||||
public class BSShapeHull : BSShape
|
||||
{
|
||||
private static string LogHeader = "[BULLETSIM SHAPE HULL]";
|
||||
private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>();
|
||||
|
||||
public BSShapeHull() : base()
|
||||
public BSShapeHull(BulletShape pShape) : base(pShape)
|
||||
{
|
||||
}
|
||||
public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
|
||||
{
|
||||
return new BSShapeNull();
|
||||
}
|
||||
public override void Dereference(BSScene physicsScene)
|
||||
{
|
||||
}
|
||||
public static BSShape GetReference() { return new BSShapeNull(); }
|
||||
public override void Dereference(BSScene physicsScene) { }
|
||||
}
|
||||
|
||||
// ============================================================================================================
|
||||
public class BSShapeCompound : BSShape
|
||||
{
|
||||
private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]";
|
||||
|
@ -216,6 +354,7 @@ public class BSShapeCompound : BSShape
|
|||
public override void Dereference(BSScene physicsScene) { }
|
||||
}
|
||||
|
||||
// ============================================================================================================
|
||||
public class BSShapeAvatar : BSShape
|
||||
{
|
||||
private static string LogHeader = "[BULLETSIM SHAPE AVATAR]";
|
||||
|
|
Loading…
Reference in New Issue