BulletSim: massive refactor of shape classes. Removed shape specific code from BSShapeCollection. Using BSShape* classes to hold references to shape. Simplified shape dependency callbacks. Remove 'PreferredShape' methods and have each class specify shape type. Disable compound shape linkset for a later commit that will simplify linkset implementation.

user_profiles
Robert Adams 2013-04-28 14:44:21 -07:00
parent 890cb6a293
commit e5582939fd
20 changed files with 293 additions and 1053 deletions

View File

@ -79,7 +79,7 @@ private sealed class BulletShapeUnman : BulletShape
: base()
{
ptr = xx;
type = typ;
shapeType = typ;
}
public override bool HasPhysicalShape
{
@ -91,7 +91,7 @@ private sealed class BulletShapeUnman : BulletShape
}
public override BulletShape Clone()
{
return new BulletShapeUnman(ptr, type);
return new BulletShapeUnman(ptr, shapeType);
}
public override bool ReferenceSame(BulletShape other)
{
@ -375,7 +375,7 @@ public override BulletShape DuplicateCollisionShape(BulletWorld world, BulletSha
{
BulletWorldUnman worldu = world as BulletWorldUnman;
BulletShapeUnman srcShapeu = srcShape as BulletShapeUnman;
return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.type);
return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.shapeType);
}
public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape)

View File

@ -85,7 +85,7 @@ private sealed class BulletShapeXNA : BulletShape
: base()
{
shape = xx;
type = typ;
shapeType = typ;
}
public override bool HasPhysicalShape
{
@ -97,7 +97,7 @@ private sealed class BulletShapeXNA : BulletShape
}
public override BulletShape Clone()
{
return new BulletShapeXNA(shape, type);
return new BulletShapeXNA(shape, shapeType);
}
public override bool ReferenceSame(BulletShape other)
{

View File

@ -87,8 +87,8 @@ public class BSActorAvatarMove : BSActor
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
// Register a prestep action to restore physical requirements before the next simulation step.
// Called at taint-time.
// BSActor.RemoveBodyDependencies()
public override void RemoveBodyDependencies()
// BSActor.RemoveDependencies()
public override void RemoveDependencies()
{
// Nothing to do for the hoverer since it is all software at pre-step action time.
}

View File

@ -87,8 +87,8 @@ public class BSActorHover : BSActor
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
// Register a prestep action to restore physical requirements before the next simulation step.
// Called at taint-time.
// BSActor.RemoveBodyDependencies()
public override void RemoveBodyDependencies()
// BSActor.RemoveDependencies()
public override void RemoveDependencies()
{
// Nothing to do for the hoverer since it is all software at pre-step action time.
}

View File

@ -85,8 +85,8 @@ public class BSActorLockAxis : BSActor
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
// Register a prestep action to restore physical requirements before the next simulation step.
// Called at taint-time.
// BSActor.RemoveBodyDependencies()
public override void RemoveBodyDependencies()
// BSActor.RemoveDependencies()
public override void RemoveDependencies()
{
if (LockAxisConstraint != null)
{

View File

@ -88,8 +88,8 @@ public class BSActorMoveToTarget : BSActor
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
// Register a prestep action to restore physical requirements before the next simulation step.
// Called at taint-time.
// BSActor.RemoveBodyDependencies()
public override void RemoveBodyDependencies()
// BSActor.RemoveDependencies()
public override void RemoveDependencies()
{
// Nothing to do for the moveToTarget since it is all software at pre-step action time.
}

View File

@ -89,8 +89,8 @@ public class BSActorSetForce : BSActor
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
// Register a prestep action to restore physical requirements before the next simulation step.
// Called at taint-time.
// BSActor.RemoveBodyDependencies()
public override void RemoveBodyDependencies()
// BSActor.RemoveDependencies()
public override void RemoveDependencies()
{
// Nothing to do for the hoverer since it is all software at pre-step action time.
}

View File

@ -89,8 +89,8 @@ public class BSActorSetTorque : BSActor
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
// Register a prestep action to restore physical requirements before the next simulation step.
// Called at taint-time.
// BSActor.RemoveBodyDependencies()
public override void RemoveBodyDependencies()
// BSActor.RemoveDependencies()
public override void RemoveDependencies()
{
// Nothing to do for the hoverer since it is all software at pre-step action time.
}

View File

@ -106,9 +106,9 @@ public class BSActorCollection
{
ForEachActor(a => a.Refresh());
}
public void RemoveBodyDependencies()
public void RemoveDependencies()
{
ForEachActor(a => a.RemoveBodyDependencies());
ForEachActor(a => a.RemoveDependencies());
}
}
@ -154,7 +154,7 @@ public abstract class BSActor
public abstract void Refresh();
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
// Register a prestep action to restore physical requirements before the next simulation step.
public abstract void RemoveBodyDependencies();
public abstract void RemoveDependencies();
}
}

View File

@ -123,8 +123,8 @@ public sealed class BSCharacter : BSPhysObject
{
PhysicsScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */);
PhysBody.Clear();
PhysicsScene.Shapes.DereferenceShape(PhysShape, null /* bodyCallback */);
PhysShape.Clear();
PhysShape.Dereference(PhysicsScene);
PhysShape = new BSShapeNull();
});
}
@ -146,8 +146,8 @@ public sealed class BSCharacter : BSPhysObject
Flying = _flying;
PhysicsScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution);
PhysicsScene.PE.SetMargin(PhysShape, PhysicsScene.Params.collisionMargin);
PhysicsScene.PE.SetLocalScaling(PhysShape, Scale);
PhysicsScene.PE.SetMargin(PhysShape.physShapeInfo, PhysicsScene.Params.collisionMargin);
PhysicsScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
if (BSParam.CcdMotionThreshold > 0f)
{
@ -205,9 +205,9 @@ public sealed class BSCharacter : BSPhysObject
PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
{
if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape)
if (PhysBody.HasPhysicalBody && PhysShape.physShapeInfo.HasPhysicalShape)
{
PhysicsScene.PE.SetLocalScaling(PhysShape, Scale);
PhysicsScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
UpdatePhysicalMassProperties(RawMass, true);
// Make sure this change appears as a property update event
PhysicsScene.PE.PushUpdate(PhysBody);
@ -221,11 +221,6 @@ public sealed class BSCharacter : BSPhysObject
{
set { BaseShape = value; }
}
// I want the physics engine to make an avatar capsule
public override BSPhysicsShapeType PreferredPhysicalShape
{
get {return BSPhysicsShapeType.SHAPE_CAPSULE; }
}
public override bool Grabbed {
set { _grabbed = value; }
@ -381,7 +376,7 @@ public sealed class BSCharacter : BSPhysObject
}
public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
{
OMV.Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass);
OMV.Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
PhysicsScene.PE.SetMassProps(PhysBody, physMass, localInertia);
}

View File

@ -625,7 +625,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Vehicles report collision events so we know when it's on the ground
m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape, m_vehicleMass);
ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass);
m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia);
m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody);
@ -649,7 +649,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
}
// BSActor.RemoveBodyDependencies
public override void RemoveBodyDependencies()
public override void RemoveDependencies()
{
Refresh();
}

View File

@ -93,13 +93,6 @@ public abstract class BSLinkset
// to the physical representation is done via the tainting mechenism.
protected object m_linksetActivityLock = new Object();
// Some linksets have a preferred physical shape.
// Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor)
{
return BSPhysicsShapeType.SHAPE_UNKNOWN;
}
// We keep the prim's mass in the linkset structure since it could be dependent on other prims
public float LinksetMass { get; protected set; }
@ -263,7 +256,7 @@ public abstract class BSLinkset
// This is called when the root body is changing.
// Returns 'true' of something was actually removed and would need restoring
// Called at taint-time!!
public abstract bool RemoveBodyDependencies(BSPrimLinkable child);
public abstract bool RemoveDependencies(BSPrimLinkable child);
// ================================================================
protected virtual float ComputeLinksetMass()

View File

@ -98,19 +98,6 @@ public sealed class BSLinksetCompound : BSLinkset
{
}
// For compound implimented linksets, if there are children, use compound shape for the root.
public override BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor)
{
// Returning 'unknown' means we don't have a preference.
BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
if (IsRoot(requestor) && HasAnyChildren)
{
ret = BSPhysicsShapeType.SHAPE_COMPOUND;
}
// DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret);
return ret;
}
// When physical properties are changed the linkset needs to recalculate
// its internal properties.
public override void Refresh(BSPrimLinkable requestor)
@ -218,22 +205,22 @@ public sealed class BSLinksetCompound : BSLinkset
// and that is caused by us updating the object.
if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0)
{
// Find the physical instance of the child
if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape))
// Find the physical instance of the child
if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape.physShapeInfo))
{
// It is possible that the linkset is still under construction and the child is not yet
// inserted into the compound shape. A rebuild of the linkset in a pre-step action will
// build the whole thing with the new position or rotation.
// The index must be checked because Bullet references the child array but does no validity
// checking of the child index passed.
int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape);
int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape.physShapeInfo);
if (updated.LinksetChildIndex < numLinksetChildren)
{
BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, updated.LinksetChildIndex);
BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex);
if (linksetChildShape.HasPhysicalShape)
{
// Found the child shape within the compound shape
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, updated.LinksetChildIndex,
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex,
updated.RawPosition - LinksetRoot.RawPosition,
updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation),
true /* shouldRecalculateLocalAabb */);
@ -278,7 +265,7 @@ public sealed class BSLinksetCompound : BSLinkset
// Since we don't keep in world relationships, do nothing unless it's a child changing.
// Returns 'true' of something was actually removed and would need restoring
// Called at taint-time!!
public override bool RemoveBodyDependencies(BSPrimLinkable child)
public override bool RemoveDependencies(BSPrimLinkable child)
{
bool ret = false;
@ -404,11 +391,12 @@ public sealed class BSLinksetCompound : BSLinkset
{
try
{
/*
// Suppress rebuilding while rebuilding. (We know rebuilding is on only one thread.)
Rebuilding = true;
// Cause the root shape to be rebuilt as a compound object with just the root in it
LinksetRoot.ForceBodyShapeRebuild(true /* inTaintTime */);
LinksetRoot.ForceBodyShapeRebuild(true /* inTaintTime );
// The center of mass for the linkset is the geometric center of the group.
// Compute a displacement for each component so it is relative to the center-of-mass.
@ -430,10 +418,10 @@ public sealed class BSLinksetCompound : BSLinkset
LinksetRoot.ForcePosition = LinksetRoot.RawPosition;
// Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0 /* childIndex */,
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape.physShapeInfo, 0 /* childIndex ,
-centerDisplacement,
OMV.Quaternion.Identity, // LinksetRoot.RawOrientation,
false /* shouldRecalculateLocalAabb (is done later after linkset built) */);
false /* shouldRecalculateLocalAabb (is done later after linkset built) );
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
LinksetRoot.LocalID, centerOfMassW, LinksetRoot.RawPosition, centerDisplacement);
@ -501,6 +489,7 @@ public sealed class BSLinksetCompound : BSLinkset
// Enable the physical position updator to return the position and rotation of the root shape
PhysicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE);
*/
}
finally
{
@ -508,7 +497,7 @@ public sealed class BSLinksetCompound : BSLinkset
}
// See that the Aabb surrounds the new shape
PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape);
PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape.physShapeInfo);
}
}
}

View File

@ -93,11 +93,11 @@ public sealed class BSLinksetConstraints : BSLinkset
// up to rebuild the constraints before the next simulation step.
// Returns 'true' of something was actually removed and would need restoring
// Called at taint-time!!
public override bool RemoveBodyDependencies(BSPrimLinkable child)
public override bool RemoveDependencies(BSPrimLinkable child)
{
bool ret = false;
DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}",
DetailLog("{0},BSLinksetConstraint.RemoveDependencies,removeChildrenForRoot,rID={1},rBody={2}",
child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString);
lock (m_linksetActivityLock)

View File

@ -88,7 +88,7 @@ public abstract class BSPhysObject : PhysicsActor
// We don't have any physical representation yet.
PhysBody = new BulletBody(localID);
PhysShape = new BulletShape();
PhysShape = new BSShapeNull();
PrimAssetState = PrimAssetCondition.Unknown;
@ -138,7 +138,7 @@ public abstract class BSPhysObject : PhysicsActor
// Reference to the physical body (btCollisionObject) of this object
public BulletBody PhysBody;
// Reference to the physical shape (btCollisionShape) of this object
public BulletShape PhysShape;
public BSShape PhysShape;
// The physical representation of the prim might require an asset fetch.
// The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'.
@ -151,13 +151,6 @@ public abstract class BSPhysObject : PhysicsActor
// The objects base shape information. Null if not a prim type shape.
public PrimitiveBaseShape BaseShape { get; protected set; }
// Some types of objects have preferred physical representations.
// Returns SHAPE_UNKNOWN if there is no preference.
public virtual BSPhysicsShapeType PreferredPhysicalShape
{
get { return BSPhysicsShapeType.SHAPE_UNKNOWN; }
}
// When the physical properties are updated, an EntityProperty holds the update values.
// Keep the current and last EntityProperties to enable computation of differences
// between the current update and the previous values.

View File

@ -134,8 +134,8 @@ public class BSPrim : BSPhysObject
// If there are physical body and shape, release my use of same.
PhysicsScene.Shapes.DereferenceBody(PhysBody, null);
PhysBody.Clear();
PhysicsScene.Shapes.DereferenceShape(PhysShape, null);
PhysShape.Clear();
PhysShape.Dereference(PhysicsScene);
PhysShape = new BSShapeNull();
});
}
@ -161,25 +161,13 @@ public class BSPrim : BSPhysObject
ForceBodyShapeRebuild(false);
}
}
// 'unknown' says to choose the best type
public override BSPhysicsShapeType PreferredPhysicalShape
{ get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } }
public override bool ForceBodyShapeRebuild(bool inTaintTime)
{
if (inTaintTime)
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
{
_mass = CalculateMass(); // changing the shape changes the mass
CreateGeomAndObject(true);
}
else
{
PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate()
{
_mass = CalculateMass(); // changing the shape changes the mass
CreateGeomAndObject(true);
});
}
});
return true;
}
public override bool Grabbed {
@ -462,7 +450,7 @@ public class BSPrim : BSPhysObject
Gravity = ComputeGravity(Buoyancy);
PhysicsScene.PE.SetGravity(PhysBody, Gravity);
Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass);
Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
PhysicsScene.PE.SetMassProps(PhysBody, physMass, Inertia);
PhysicsScene.PE.UpdateInertiaTensor(PhysBody);
@ -805,7 +793,8 @@ public class BSPrim : BSPhysObject
PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody);
DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}",
LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape);
LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(),
CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape);
}
// "Making dynamic" means changing to and from static.
@ -1463,12 +1452,13 @@ public class BSPrim : BSPhysObject
// Create the correct physical representation for this type of object.
// Updates base.PhysBody and base.PhysShape with the new information.
// Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary.
PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody)
PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, delegate(BulletBody pBody, BulletShape pShape)
{
// Called if the current prim body is about to be destroyed.
// Remove all the physical dependencies on the old body.
// (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...)
RemoveBodyDependencies();
// Note: this virtual function is overloaded by BSPrimLinkable to remove linkset constraints.
RemoveDependencies();
});
// Make sure the properties are set on the new object
@ -1477,9 +1467,9 @@ public class BSPrim : BSPhysObject
}
// Called at taint-time
protected virtual void RemoveBodyDependencies()
protected virtual void RemoveDependencies()
{
PhysicalActors.RemoveBodyDependencies();
PhysicalActors.RemoveDependencies();
}
// The physics engine says that properties have updated. Update same and inform

View File

@ -61,9 +61,6 @@ public class BSPrimLinkable : BSPrimDisplaced
base.Destroy();
}
public override BSPhysicsShapeType PreferredPhysicalShape
{ get { return Linkset.PreferredPhysicalShape(this); } }
public override void link(Manager.PhysicsActor obj)
{
BSPrimLinkable parent = obj as BSPrimLinkable;
@ -149,10 +146,10 @@ public class BSPrimLinkable : BSPrimDisplaced
}
// Body is being taken apart. Remove physical dependencies and schedule a rebuild.
protected override void RemoveBodyDependencies()
protected override void RemoveDependencies()
{
Linkset.RemoveBodyDependencies(this);
base.RemoveBodyDependencies();
Linkset.RemoveDependencies(this);
base.RemoveDependencies();
}
public override void UpdateProperties(EntityProperties entprop)

File diff suppressed because it is too large Load Diff

View File

@ -39,6 +39,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{
public abstract class BSShape
{
private static string LogHeader = "[BULLETSIM SHAPE]";
public int referenceCount { get; set; }
public DateTime lastReferenced { get; set; }
public BulletShape physShapeInfo { get; set; }
@ -56,49 +58,6 @@ public abstract class BSShape
physShapeInfo = pShape;
}
// Get a reference to a physical shape. Create if it doesn't exist
public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
{
BSShape ret = null;
if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE)
{
// an avatar capsule is close to a native shape (it is not shared)
ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE,
FixedShapeKey.KEY_CAPSULE);
physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret);
}
// Compound shapes are handled special as they are rebuilt from scratch.
// This isn't too great a hardship since most of the child shapes will have already been created.
if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
{
// Getting a reference to a compound shape gets you the compound shape with the root prim shape added
ret = BSShapeCompound.GetReference(physicsScene, prim);
physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
}
// Avatars have their own unique shape
if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_AVATAR)
{
// Getting a reference to a compound shape gets you the compound shape with the root prim shape added
ret = BSShapeAvatar.GetReference(prim);
physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,avatarShape,shape={1}", prim.LocalID, ret);
}
if (ret == null)
ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim);
return ret;
}
private static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
{
// TODO: work needed here!!
BSShapeMesh.GetReference(physicsScene, forceRebuild, prim);
BSShapeHull.GetReference(physicsScene, forceRebuild, prim);
return null;
}
// Called when this shape is being used again.
public virtual void IncrementReference()
{
@ -116,6 +75,27 @@ public abstract class BSShape
// Release the use of a physical shape.
public abstract void Dereference(BSScene physicsScene);
// Return 'true' if there is an allocated physics physical shape under this class instance.
public virtual bool HasPhysicalShape
{
get
{
if (physShapeInfo != null)
return physShapeInfo.HasPhysicalShape;
return false;
}
}
public virtual BSPhysicsShapeType ShapeType
{
get
{
BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
if (physShapeInfo != null && physShapeInfo.HasPhysicalShape)
ret = physShapeInfo.shapeType;
return ret;
}
}
// Returns a string for debugging that uniquily identifies the memory used by this instance
public virtual string AddrString
{
@ -132,6 +112,119 @@ public abstract class BSShape
buff.Append(">");
return buff.ToString();
}
// Create a hash of all the shape parameters to be used as a key for this particular shape.
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;
if (pbs.SculptEntry)
lod = BSParam.SculptLOD;
// Mega prims usually get more detail because one can interact with shape approximations at this size.
float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
if (maxAxis > BSParam.MeshMegaPrimThreshold)
lod = BSParam.MeshMegaPrimLOD;
retLod = lod;
return pbs.GetMeshKey(size, lod);
}
// The creation of a mesh or hull can fail if an underlying asset is not available.
// There are two cases: 1) the asset is not in the cache and it needs to be fetched;
// and 2) the asset cannot be converted (like failed decompression of JPEG2000s).
// The first case causes the asset to be fetched. The second case requires
// us to not loop forever.
// Called after creating a physical mesh or hull. If the physical shape was created,
// just return.
public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim)
{
// If the shape was successfully created, nothing more to do
if (newShape.HasPhysicalShape)
return newShape;
// VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been
// fetched but we end up here again, the meshing of the asset must have failed.
// Prevent trying to keep fetching the mesh by declaring failure.
if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
{
prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
}
else
{
// If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
if (prim.BaseShape.SculptEntry
&& prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed
&& prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting
&& prim.BaseShape.SculptTexture != OMV.UUID.Zero
)
{
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;
if (assetProvider != null)
{
BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
{
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 = 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.
yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
assetFound = true;
}
else
{
mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
}
}
if (assetFound)
yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
else
yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
physicsScene.DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
});
}
else
{
xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
LogHeader, physicsScene.Name);
}
});
}
else
{
if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
{
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.
BSShape fillShape = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID);
return fillShape.physShapeInfo;
}
}
// ============================================================================================================
@ -199,7 +292,7 @@ public class BSShapeNative : BSShape
physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
LogHeader, prim.LocalID, shapeType);
}
newShape.type = shapeType;
newShape.shapeType = shapeType;
newShape.isNativeShape = true;
newShape.shapeKey = (UInt64)shapeKey;
return newShape;
@ -219,10 +312,11 @@ public class BSShapeMesh : BSShape
public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
{
float lod;
System.UInt64 newMeshKey = BSShapeCollection.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}",
prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod);
prim.LocalID, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"),
newMeshKey.ToString("X"), prim.Size, lod);
BSShapeMesh retMesh = new BSShapeMesh(new BulletShape());
lock (Meshes)
@ -238,8 +332,8 @@ public class BSShapeMesh : BSShape
BulletShape newShape = retMesh.CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);
// Check to see if mesh was created (might require an asset).
newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim);
if (newShape.type == BSPhysicsShapeType.SHAPE_MESH)
newShape = VerifyMeshCreated(physicsScene, newShape, prim);
if (newShape.shapeType == BSPhysicsShapeType.SHAPE_MESH)
{
// If a mesh was what was created, remember the built shape for later sharing.
Meshes.Add(newMeshKey, retMesh);
@ -360,10 +454,10 @@ public class BSShapeHull : BSShape
public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
{
float lod;
System.UInt64 newHullKey = BSShapeCollection.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}",
prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"), prim.Size, lod);
prim.LocalID, prim.PhysShape.physShapeInfo.shapeKey.ToString("X"), newHullKey.ToString("X"), prim.Size, lod);
BSShapeHull retHull = new BSShapeHull(new BulletShape());
lock (Hulls)
@ -379,8 +473,8 @@ public class BSShapeHull : BSShape
BulletShape newShape = retHull.CreatePhysicalHull(physicsScene, prim, newHullKey, prim.BaseShape, prim.Size, lod);
// Check to see if mesh was created (might require an asset).
newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim);
if (newShape.type == BSPhysicsShapeType.SHAPE_MESH)
newShape = VerifyMeshCreated(physicsScene, newShape, prim);
if (newShape.shapeType == BSPhysicsShapeType.SHAPE_MESH)
{
// If a mesh was what was created, remember the built shape for later sharing.
Hulls.Add(newHullKey, retHull);
@ -569,7 +663,6 @@ public class BSShapeHull : BSShape
}
}
// ============================================================================================================
public class BSShapeCompound : BSShape
{
@ -589,9 +682,9 @@ public class BSShapeCompound : BSShape
{
// Failed the sanity check!!
physicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
LogHeader, physShapeInfo.type, physShapeInfo.AddrString);
LogHeader, physShapeInfo.shapeType, physShapeInfo.AddrString);
physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
BSScene.DetailLogZero, physShapeInfo.type, physShapeInfo.AddrString);
BSScene.DetailLogZero, physShapeInfo.shapeType, physShapeInfo.AddrString);
return;
}

View File

@ -104,11 +104,11 @@ public class BulletShape
{
public BulletShape()
{
type = BSPhysicsShapeType.SHAPE_UNKNOWN;
shapeType = BSPhysicsShapeType.SHAPE_UNKNOWN;
shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE;
isNativeShape = false;
}
public BSPhysicsShapeType type;
public BSPhysicsShapeType shapeType;
public System.UInt64 shapeKey;
public bool isNativeShape;
@ -133,7 +133,7 @@ public class BulletShape
buff.Append("<p=");
buff.Append(AddrString);
buff.Append(",s=");
buff.Append(type.ToString());
buff.Append(shapeType.ToString());
buff.Append(",k=");
buff.Append(shapeKey.ToString("X"));
buff.Append(",n=");