BulletSim: add asset fetching so BulletSim works with new physics asset handling.
Refactor some names to make them available for the asset tracking and fetching.connector_plugin
parent
f422b9b388
commit
d94c4646cc
|
@ -200,10 +200,9 @@ public class BSCharacter : BSPhysObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public override OMV.Vector3 Scale { get; set; }
|
public override OMV.Vector3 Scale { get; set; }
|
||||||
private PrimitiveBaseShape _pbs;
|
|
||||||
public override PrimitiveBaseShape Shape
|
public override PrimitiveBaseShape Shape
|
||||||
{
|
{
|
||||||
set { _pbs = value;}
|
set { BaseShape = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Grabbed {
|
public override bool Grabbed {
|
||||||
|
|
|
@ -47,6 +47,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
TypeName = typeName;
|
TypeName = typeName;
|
||||||
|
|
||||||
Linkset = new BSLinkset(PhysicsScene, this);
|
Linkset = new BSLinkset(PhysicsScene, this);
|
||||||
|
LastAssetBuildFailed = false;
|
||||||
|
|
||||||
CollisionCollection = new CollisionEventUpdate();
|
CollisionCollection = new CollisionEventUpdate();
|
||||||
SubscribedEventsMs = 0;
|
SubscribedEventsMs = 0;
|
||||||
|
@ -69,6 +70,13 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
// Reference to the physical shape (btCollisionShape) of this object
|
// Reference to the physical shape (btCollisionShape) of this object
|
||||||
public BulletShape BSShape;
|
public BulletShape BSShape;
|
||||||
|
|
||||||
|
// 'true' if the mesh's underlying asset failed to build.
|
||||||
|
// This will keep us from looping after the first time the build failed.
|
||||||
|
public bool LastAssetBuildFailed { get; set; }
|
||||||
|
|
||||||
|
// The objects base shape information. Null if not a prim type shape.
|
||||||
|
public PrimitiveBaseShape BaseShape { get; protected set; }
|
||||||
|
|
||||||
// When the physical properties are updated, an EntityProperty holds the update values.
|
// When the physical properties are updated, an EntityProperty holds the update values.
|
||||||
// Keep the current and last EntityProperties to enable computation of differences
|
// Keep the current and last EntityProperties to enable computation of differences
|
||||||
// between the current update and the previous values.
|
// between the current update and the previous values.
|
||||||
|
@ -101,6 +109,8 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
|
|
||||||
public abstract float ForceBuoyancy { get; set; }
|
public abstract float ForceBuoyancy { get; set; }
|
||||||
|
|
||||||
|
public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
|
||||||
|
|
||||||
#region Collisions
|
#region Collisions
|
||||||
|
|
||||||
// Requested number of milliseconds between collision events. Zero means disabled.
|
// Requested number of milliseconds between collision events. Zero means disabled.
|
||||||
|
|
|
@ -46,8 +46,6 @@ public sealed class BSPrim : BSPhysObject
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
private static readonly string LogHeader = "[BULLETS PRIM]";
|
private static readonly string LogHeader = "[BULLETS PRIM]";
|
||||||
|
|
||||||
private PrimitiveBaseShape _pbs;
|
|
||||||
|
|
||||||
// _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
|
// _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
|
||||||
// Often Scale is unity because the meshmerizer will apply _size when creating the mesh.
|
// Often Scale is unity because the meshmerizer will apply _size when creating the mesh.
|
||||||
private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
|
private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
|
||||||
|
@ -103,7 +101,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
_buoyancy = 1f;
|
_buoyancy = 1f;
|
||||||
_velocity = OMV.Vector3.Zero;
|
_velocity = OMV.Vector3.Zero;
|
||||||
_rotationalVelocity = OMV.Vector3.Zero;
|
_rotationalVelocity = OMV.Vector3.Zero;
|
||||||
_pbs = pbs;
|
BaseShape = pbs;
|
||||||
_isPhysical = pisPhysical;
|
_isPhysical = pisPhysical;
|
||||||
_isVolumeDetect = false;
|
_isVolumeDetect = false;
|
||||||
_friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material
|
_friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material
|
||||||
|
@ -160,14 +158,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
get { return _size; }
|
get { return _size; }
|
||||||
set {
|
set {
|
||||||
_size = value;
|
_size = value;
|
||||||
PhysicsScene.TaintedObject("BSPrim.setSize", delegate()
|
ForceBodyShapeRebuild(false);
|
||||||
{
|
|
||||||
_mass = CalculateMass(); // changing size changes the mass
|
|
||||||
// Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct
|
|
||||||
// scale and margins are set.
|
|
||||||
CreateGeomAndObject(true);
|
|
||||||
// DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, Scale, _mass, IsPhysical);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Scale is what we set in the physics engine. It is different than 'size' in that
|
// Scale is what we set in the physics engine. It is different than 'size' in that
|
||||||
|
@ -176,14 +167,23 @@ public sealed class BSPrim : BSPhysObject
|
||||||
|
|
||||||
public override PrimitiveBaseShape Shape {
|
public override PrimitiveBaseShape Shape {
|
||||||
set {
|
set {
|
||||||
_pbs = value;
|
BaseShape = value;
|
||||||
PhysicsScene.TaintedObject("BSPrim.setShape", delegate()
|
ForceBodyShapeRebuild(false);
|
||||||
{
|
|
||||||
_mass = CalculateMass(); // changing the shape changes the mass
|
|
||||||
CreateGeomAndObject(true);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public override bool ForceBodyShapeRebuild(bool inTaintTime)
|
||||||
|
{
|
||||||
|
BSScene.TaintCallback rebuildOperation = delegate()
|
||||||
|
{
|
||||||
|
_mass = CalculateMass(); // changing the shape changes the mass
|
||||||
|
CreateGeomAndObject(true);
|
||||||
|
};
|
||||||
|
if (inTaintTime)
|
||||||
|
rebuildOperation();
|
||||||
|
else
|
||||||
|
PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", rebuildOperation);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
public override bool Grabbed {
|
public override bool Grabbed {
|
||||||
set { _grabbed = value;
|
set { _grabbed = value;
|
||||||
}
|
}
|
||||||
|
@ -924,19 +924,19 @@ public sealed class BSPrim : BSPhysObject
|
||||||
float tmp;
|
float tmp;
|
||||||
|
|
||||||
float returnMass = 0;
|
float returnMass = 0;
|
||||||
float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
|
float hollowAmount = (float)BaseShape.ProfileHollow * 2.0e-5f;
|
||||||
float hollowVolume = hollowAmount * hollowAmount;
|
float hollowVolume = hollowAmount * hollowAmount;
|
||||||
|
|
||||||
switch (_pbs.ProfileShape)
|
switch (BaseShape.ProfileShape)
|
||||||
{
|
{
|
||||||
case ProfileShape.Square:
|
case ProfileShape.Square:
|
||||||
// default box
|
// default box
|
||||||
|
|
||||||
if (_pbs.PathCurve == (byte)Extrusion.Straight)
|
if (BaseShape.PathCurve == (byte)Extrusion.Straight)
|
||||||
{
|
{
|
||||||
if (hollowAmount > 0.0)
|
if (hollowAmount > 0.0)
|
||||||
{
|
{
|
||||||
switch (_pbs.HollowShape)
|
switch (BaseShape.HollowShape)
|
||||||
{
|
{
|
||||||
case HollowShape.Square:
|
case HollowShape.Square:
|
||||||
case HollowShape.Same:
|
case HollowShape.Same:
|
||||||
|
@ -960,19 +960,19 @@ public sealed class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
|
else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
|
||||||
{
|
{
|
||||||
//a tube
|
//a tube
|
||||||
|
|
||||||
volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
|
volume *= 0.78539816339e-2f * (float)(200 - BaseShape.PathScaleX);
|
||||||
tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY);
|
tmp= 1.0f -2.0e-2f * (float)(200 - BaseShape.PathScaleY);
|
||||||
volume -= volume*tmp*tmp;
|
volume -= volume*tmp*tmp;
|
||||||
|
|
||||||
if (hollowAmount > 0.0)
|
if (hollowAmount > 0.0)
|
||||||
{
|
{
|
||||||
hollowVolume *= hollowAmount;
|
hollowVolume *= hollowAmount;
|
||||||
|
|
||||||
switch (_pbs.HollowShape)
|
switch (BaseShape.HollowShape)
|
||||||
{
|
{
|
||||||
case HollowShape.Square:
|
case HollowShape.Square:
|
||||||
case HollowShape.Same:
|
case HollowShape.Same:
|
||||||
|
@ -997,13 +997,13 @@ public sealed class BSPrim : BSPhysObject
|
||||||
|
|
||||||
case ProfileShape.Circle:
|
case ProfileShape.Circle:
|
||||||
|
|
||||||
if (_pbs.PathCurve == (byte)Extrusion.Straight)
|
if (BaseShape.PathCurve == (byte)Extrusion.Straight)
|
||||||
{
|
{
|
||||||
volume *= 0.78539816339f; // elipse base
|
volume *= 0.78539816339f; // elipse base
|
||||||
|
|
||||||
if (hollowAmount > 0.0)
|
if (hollowAmount > 0.0)
|
||||||
{
|
{
|
||||||
switch (_pbs.HollowShape)
|
switch (BaseShape.HollowShape)
|
||||||
{
|
{
|
||||||
case HollowShape.Same:
|
case HollowShape.Same:
|
||||||
case HollowShape.Circle:
|
case HollowShape.Circle:
|
||||||
|
@ -1025,10 +1025,10 @@ public sealed class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
|
else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
|
||||||
{
|
{
|
||||||
volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
|
volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - BaseShape.PathScaleX);
|
||||||
tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
|
tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY);
|
||||||
volume *= (1.0f - tmp * tmp);
|
volume *= (1.0f - tmp * tmp);
|
||||||
|
|
||||||
if (hollowAmount > 0.0)
|
if (hollowAmount > 0.0)
|
||||||
|
@ -1037,7 +1037,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
// calculate the hollow volume by it's shape compared to the prim shape
|
// calculate the hollow volume by it's shape compared to the prim shape
|
||||||
hollowVolume *= hollowAmount;
|
hollowVolume *= hollowAmount;
|
||||||
|
|
||||||
switch (_pbs.HollowShape)
|
switch (BaseShape.HollowShape)
|
||||||
{
|
{
|
||||||
case HollowShape.Same:
|
case HollowShape.Same:
|
||||||
case HollowShape.Circle:
|
case HollowShape.Circle:
|
||||||
|
@ -1061,7 +1061,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ProfileShape.HalfCircle:
|
case ProfileShape.HalfCircle:
|
||||||
if (_pbs.PathCurve == (byte)Extrusion.Curve1)
|
if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
|
||||||
{
|
{
|
||||||
volume *= 0.52359877559829887307710723054658f;
|
volume *= 0.52359877559829887307710723054658f;
|
||||||
}
|
}
|
||||||
|
@ -1069,7 +1069,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
|
|
||||||
case ProfileShape.EquilateralTriangle:
|
case ProfileShape.EquilateralTriangle:
|
||||||
|
|
||||||
if (_pbs.PathCurve == (byte)Extrusion.Straight)
|
if (BaseShape.PathCurve == (byte)Extrusion.Straight)
|
||||||
{
|
{
|
||||||
volume *= 0.32475953f;
|
volume *= 0.32475953f;
|
||||||
|
|
||||||
|
@ -1077,7 +1077,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
{
|
{
|
||||||
|
|
||||||
// calculate the hollow volume by it's shape compared to the prim shape
|
// calculate the hollow volume by it's shape compared to the prim shape
|
||||||
switch (_pbs.HollowShape)
|
switch (BaseShape.HollowShape)
|
||||||
{
|
{
|
||||||
case HollowShape.Same:
|
case HollowShape.Same:
|
||||||
case HollowShape.Triangle:
|
case HollowShape.Triangle:
|
||||||
|
@ -1102,11 +1102,11 @@ public sealed class BSPrim : BSPhysObject
|
||||||
volume *= (1.0f - hollowVolume);
|
volume *= (1.0f - hollowVolume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
|
else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
|
||||||
{
|
{
|
||||||
volume *= 0.32475953f;
|
volume *= 0.32475953f;
|
||||||
volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
|
volume *= 0.01f * (float)(200 - BaseShape.PathScaleX);
|
||||||
tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
|
tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY);
|
||||||
volume *= (1.0f - tmp * tmp);
|
volume *= (1.0f - tmp * tmp);
|
||||||
|
|
||||||
if (hollowAmount > 0.0)
|
if (hollowAmount > 0.0)
|
||||||
|
@ -1114,7 +1114,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
|
|
||||||
hollowVolume *= hollowAmount;
|
hollowVolume *= hollowAmount;
|
||||||
|
|
||||||
switch (_pbs.HollowShape)
|
switch (BaseShape.HollowShape)
|
||||||
{
|
{
|
||||||
case HollowShape.Same:
|
case HollowShape.Same:
|
||||||
case HollowShape.Triangle:
|
case HollowShape.Triangle:
|
||||||
|
@ -1154,26 +1154,26 @@ public sealed class BSPrim : BSPhysObject
|
||||||
float profileBegin;
|
float profileBegin;
|
||||||
float profileEnd;
|
float profileEnd;
|
||||||
|
|
||||||
if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
|
if (BaseShape.PathCurve == (byte)Extrusion.Straight || BaseShape.PathCurve == (byte)Extrusion.Flexible)
|
||||||
{
|
{
|
||||||
taperX1 = _pbs.PathScaleX * 0.01f;
|
taperX1 = BaseShape.PathScaleX * 0.01f;
|
||||||
if (taperX1 > 1.0f)
|
if (taperX1 > 1.0f)
|
||||||
taperX1 = 2.0f - taperX1;
|
taperX1 = 2.0f - taperX1;
|
||||||
taperX = 1.0f - taperX1;
|
taperX = 1.0f - taperX1;
|
||||||
|
|
||||||
taperY1 = _pbs.PathScaleY * 0.01f;
|
taperY1 = BaseShape.PathScaleY * 0.01f;
|
||||||
if (taperY1 > 1.0f)
|
if (taperY1 > 1.0f)
|
||||||
taperY1 = 2.0f - taperY1;
|
taperY1 = 2.0f - taperY1;
|
||||||
taperY = 1.0f - taperY1;
|
taperY = 1.0f - taperY1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
taperX = _pbs.PathTaperX * 0.01f;
|
taperX = BaseShape.PathTaperX * 0.01f;
|
||||||
if (taperX < 0.0f)
|
if (taperX < 0.0f)
|
||||||
taperX = -taperX;
|
taperX = -taperX;
|
||||||
taperX1 = 1.0f - taperX;
|
taperX1 = 1.0f - taperX;
|
||||||
|
|
||||||
taperY = _pbs.PathTaperY * 0.01f;
|
taperY = BaseShape.PathTaperY * 0.01f;
|
||||||
if (taperY < 0.0f)
|
if (taperY < 0.0f)
|
||||||
taperY = -taperY;
|
taperY = -taperY;
|
||||||
taperY1 = 1.0f - taperY;
|
taperY1 = 1.0f - taperY;
|
||||||
|
@ -1183,13 +1183,13 @@ public sealed class BSPrim : BSPhysObject
|
||||||
|
|
||||||
volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
|
volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
|
||||||
|
|
||||||
pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
|
pathBegin = (float)BaseShape.PathBegin * 2.0e-5f;
|
||||||
pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
|
pathEnd = 1.0f - (float)BaseShape.PathEnd * 2.0e-5f;
|
||||||
volume *= (pathEnd - pathBegin);
|
volume *= (pathEnd - pathBegin);
|
||||||
|
|
||||||
// this is crude aproximation
|
// this is crude aproximation
|
||||||
profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
|
profileBegin = (float)BaseShape.ProfileBegin * 2.0e-5f;
|
||||||
profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
|
profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f;
|
||||||
volume *= (profileEnd - profileBegin);
|
volume *= (profileEnd - profileBegin);
|
||||||
|
|
||||||
returnMass = _density * volume;
|
returnMass = _density * volume;
|
||||||
|
@ -1251,7 +1251,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
// Create the correct physical representation for this type of object.
|
// Create the correct physical representation for this type of object.
|
||||||
// Updates BSBody and BSShape with the new information.
|
// Updates BSBody and BSShape with the new information.
|
||||||
// Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
|
// Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
|
||||||
PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, _pbs,
|
PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape,
|
||||||
null, delegate(BulletBody dBody)
|
null, delegate(BulletBody dBody)
|
||||||
{
|
{
|
||||||
// Called if the current prim body is about to be destroyed.
|
// Called if the current prim body is about to be destroyed.
|
||||||
|
|
|
@ -117,7 +117,7 @@ public class BSShapeCollection : IDisposable
|
||||||
|
|
||||||
// Track another user of a body
|
// Track another user of a body
|
||||||
// We presume the caller has allocated the body.
|
// We presume the caller has allocated the body.
|
||||||
// Bodies only have one user so the reference count is either 1 or 0.
|
// Bodies only have one user so the body is just put into the world if not already there.
|
||||||
public void ReferenceBody(BulletBody body, bool inTaintTime)
|
public void ReferenceBody(BulletBody body, bool inTaintTime)
|
||||||
{
|
{
|
||||||
lock (m_collectionActivityLock)
|
lock (m_collectionActivityLock)
|
||||||
|
@ -241,26 +241,32 @@ public class BSShapeCollection : IDisposable
|
||||||
|
|
||||||
BSScene.TaintCallback dereferenceOperation = delegate()
|
BSScene.TaintCallback dereferenceOperation = delegate()
|
||||||
{
|
{
|
||||||
switch (shape.type)
|
if (shape.ptr != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
case ShapeData.PhysicsShapeType.SHAPE_HULL:
|
if (shape.isNativeShape)
|
||||||
DereferenceHull(shape, shapeCallback);
|
{
|
||||||
break;
|
|
||||||
case ShapeData.PhysicsShapeType.SHAPE_MESH:
|
|
||||||
DereferenceMesh(shape, shapeCallback);
|
|
||||||
break;
|
|
||||||
case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Native shapes are not tracked and are released immediately
|
// Native shapes are not tracked and are released immediately
|
||||||
if (shape.ptr != IntPtr.Zero & shape.isNativeShape)
|
DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
|
||||||
|
BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime);
|
||||||
|
if (shapeCallback != null) shapeCallback(shape);
|
||||||
|
BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (shape.type)
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
|
case ShapeData.PhysicsShapeType.SHAPE_HULL:
|
||||||
BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime);
|
DereferenceHull(shape, shapeCallback);
|
||||||
if (shapeCallback != null) shapeCallback(shape);
|
break;
|
||||||
BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
|
case ShapeData.PhysicsShapeType.SHAPE_MESH:
|
||||||
|
DereferenceMesh(shape, shapeCallback);
|
||||||
|
break;
|
||||||
|
case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (inTaintTime)
|
if (inTaintTime)
|
||||||
|
@ -405,7 +411,6 @@ public class BSShapeCollection : IDisposable
|
||||||
ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey,
|
ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey,
|
||||||
ShapeDestructionCallback shapeCallback)
|
ShapeDestructionCallback shapeCallback)
|
||||||
{
|
{
|
||||||
BulletShape newShape;
|
|
||||||
|
|
||||||
shapeData.Type = shapeType;
|
shapeData.Type = shapeType;
|
||||||
// Bullet native objects are scaled by the Bullet engine so pass the size in
|
// Bullet native objects are scaled by the Bullet engine so pass the size in
|
||||||
|
@ -415,20 +420,7 @@ public class BSShapeCollection : IDisposable
|
||||||
// release any previous shape
|
// release any previous shape
|
||||||
DereferenceShape(prim.BSShape, true, shapeCallback);
|
DereferenceShape(prim.BSShape, true, shapeCallback);
|
||||||
|
|
||||||
if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR)
|
BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey);
|
||||||
{
|
|
||||||
newShape = new BulletShape(
|
|
||||||
BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale),
|
|
||||||
shapeType);
|
|
||||||
newShape.shapeKey = (System.UInt64)shapeKey;
|
|
||||||
newShape.isNativeShape = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType);
|
|
||||||
newShape.shapeKey = (System.UInt64)shapeKey;
|
|
||||||
newShape.isNativeShape = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
|
// Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
|
||||||
DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
|
DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
|
||||||
|
@ -438,6 +430,27 @@ public class BSShapeCollection : IDisposable
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType,
|
||||||
|
ShapeData shapeData, ShapeData.FixedShapeKey shapeKey)
|
||||||
|
{
|
||||||
|
BulletShape newShape;
|
||||||
|
|
||||||
|
if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR)
|
||||||
|
{
|
||||||
|
newShape = new BulletShape(
|
||||||
|
BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale),
|
||||||
|
shapeType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType);
|
||||||
|
}
|
||||||
|
newShape.shapeKey = (System.UInt64)shapeKey;
|
||||||
|
newShape.isNativeShape = true;
|
||||||
|
|
||||||
|
return newShape;
|
||||||
|
}
|
||||||
|
|
||||||
// Builds a mesh shape in the physical world and updates prim.BSShape.
|
// Builds a mesh shape in the physical world and updates prim.BSShape.
|
||||||
// Dereferences previous shape in BSShape and adds a reference for this new shape.
|
// Dereferences previous shape in BSShape and adds a reference for this new shape.
|
||||||
// Returns 'true' of a mesh was actually built. Otherwise .
|
// Returns 'true' of a mesh was actually built. Otherwise .
|
||||||
|
@ -461,6 +474,8 @@ public class BSShapeCollection : IDisposable
|
||||||
DereferenceShape(prim.BSShape, true, shapeCallback);
|
DereferenceShape(prim.BSShape, true, shapeCallback);
|
||||||
|
|
||||||
newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod);
|
newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod);
|
||||||
|
// Take evasive action if the mesh was not constructed.
|
||||||
|
newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs);
|
||||||
|
|
||||||
ReferenceShape(newShape);
|
ReferenceShape(newShape);
|
||||||
|
|
||||||
|
@ -474,7 +489,7 @@ public class BSShapeCollection : IDisposable
|
||||||
private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
|
private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
|
||||||
{
|
{
|
||||||
IMesh meshData = null;
|
IMesh meshData = null;
|
||||||
IntPtr meshPtr;
|
IntPtr meshPtr = IntPtr.Zero;
|
||||||
MeshDesc meshDesc;
|
MeshDesc meshDesc;
|
||||||
if (Meshes.TryGetValue(newMeshKey, out meshDesc))
|
if (Meshes.TryGetValue(newMeshKey, out meshDesc))
|
||||||
{
|
{
|
||||||
|
@ -486,23 +501,26 @@ public class BSShapeCollection : IDisposable
|
||||||
// Pass false for physicalness as this creates some sort of bounding box which we don't need
|
// Pass false for physicalness as this creates some sort of bounding box which we don't need
|
||||||
meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
|
meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
|
||||||
|
|
||||||
int[] indices = meshData.getIndexListAsInt();
|
if (meshData != null)
|
||||||
List<OMV.Vector3> vertices = meshData.getVertexList();
|
|
||||||
|
|
||||||
float[] verticesAsFloats = new float[vertices.Count * 3];
|
|
||||||
int vi = 0;
|
|
||||||
foreach (OMV.Vector3 vv in vertices)
|
|
||||||
{
|
{
|
||||||
verticesAsFloats[vi++] = vv.X;
|
int[] indices = meshData.getIndexListAsInt();
|
||||||
verticesAsFloats[vi++] = vv.Y;
|
List<OMV.Vector3> vertices = meshData.getVertexList();
|
||||||
verticesAsFloats[vi++] = vv.Z;
|
|
||||||
|
float[] verticesAsFloats = new float[vertices.Count * 3];
|
||||||
|
int vi = 0;
|
||||||
|
foreach (OMV.Vector3 vv in vertices)
|
||||||
|
{
|
||||||
|
verticesAsFloats[vi++] = vv.X;
|
||||||
|
verticesAsFloats[vi++] = vv.Y;
|
||||||
|
verticesAsFloats[vi++] = vv.Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
|
||||||
|
// LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count);
|
||||||
|
|
||||||
|
meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
|
||||||
|
indices.GetLength(0), indices, vertices.Count, verticesAsFloats);
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
|
|
||||||
// LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count);
|
|
||||||
|
|
||||||
meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
|
|
||||||
indices.GetLength(0), indices, vertices.Count, verticesAsFloats);
|
|
||||||
}
|
}
|
||||||
BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH);
|
BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH);
|
||||||
newShape.shapeKey = newMeshKey;
|
newShape.shapeKey = newMeshKey;
|
||||||
|
@ -531,6 +549,7 @@ public class BSShapeCollection : IDisposable
|
||||||
DereferenceShape(prim.BSShape, true, shapeCallback);
|
DereferenceShape(prim.BSShape, true, shapeCallback);
|
||||||
|
|
||||||
newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod);
|
newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod);
|
||||||
|
newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs);
|
||||||
|
|
||||||
ReferenceShape(newShape);
|
ReferenceShape(newShape);
|
||||||
|
|
||||||
|
@ -544,7 +563,7 @@ public class BSShapeCollection : IDisposable
|
||||||
private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
|
private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
|
||||||
{
|
{
|
||||||
|
|
||||||
IntPtr hullPtr;
|
IntPtr hullPtr = IntPtr.Zero;
|
||||||
HullDesc hullDesc;
|
HullDesc hullDesc;
|
||||||
if (Hulls.TryGetValue(newHullKey, out hullDesc))
|
if (Hulls.TryGetValue(newHullKey, out hullDesc))
|
||||||
{
|
{
|
||||||
|
@ -556,86 +575,89 @@ public class BSShapeCollection : IDisposable
|
||||||
// Build a new hull in the physical world
|
// Build a new hull in the physical world
|
||||||
// Pass false for physicalness as this creates some sort of bounding box which we don't need
|
// Pass false for physicalness as this creates some sort of bounding box which we don't need
|
||||||
IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
|
IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
|
||||||
|
if (meshData != null)
|
||||||
int[] indices = meshData.getIndexListAsInt();
|
|
||||||
List<OMV.Vector3> vertices = meshData.getVertexList();
|
|
||||||
|
|
||||||
//format conversion from IMesh format to DecompDesc format
|
|
||||||
List<int> convIndices = new List<int>();
|
|
||||||
List<float3> convVertices = new List<float3>();
|
|
||||||
for (int ii = 0; ii < indices.GetLength(0); ii++)
|
|
||||||
{
|
{
|
||||||
convIndices.Add(indices[ii]);
|
|
||||||
}
|
|
||||||
foreach (OMV.Vector3 vv in vertices)
|
|
||||||
{
|
|
||||||
convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup and do convex hull conversion
|
int[] indices = meshData.getIndexListAsInt();
|
||||||
m_hulls = new List<ConvexResult>();
|
List<OMV.Vector3> vertices = meshData.getVertexList();
|
||||||
DecompDesc dcomp = new DecompDesc();
|
|
||||||
dcomp.mIndices = convIndices;
|
|
||||||
dcomp.mVertices = convVertices;
|
|
||||||
ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
|
|
||||||
// create the hull into the _hulls variable
|
|
||||||
convexBuilder.process(dcomp);
|
|
||||||
|
|
||||||
// Convert the vertices and indices for passing to unmanaged.
|
//format conversion from IMesh format to DecompDesc format
|
||||||
// The hull information is passed as a large floating point array.
|
List<int> convIndices = new List<int>();
|
||||||
// The format is:
|
List<float3> convVertices = new List<float3>();
|
||||||
// convHulls[0] = number of hulls
|
for (int ii = 0; ii < indices.GetLength(0); ii++)
|
||||||
// convHulls[1] = number of vertices in first hull
|
|
||||||
// convHulls[2] = hull centroid X coordinate
|
|
||||||
// convHulls[3] = hull centroid Y coordinate
|
|
||||||
// convHulls[4] = hull centroid Z coordinate
|
|
||||||
// convHulls[5] = first hull vertex X
|
|
||||||
// convHulls[6] = first hull vertex Y
|
|
||||||
// convHulls[7] = first hull vertex Z
|
|
||||||
// convHulls[8] = second hull vertex X
|
|
||||||
// ...
|
|
||||||
// convHulls[n] = number of vertices in second hull
|
|
||||||
// convHulls[n+1] = second hull centroid X coordinate
|
|
||||||
// ...
|
|
||||||
//
|
|
||||||
// TODO: is is very inefficient. Someday change the convex hull generator to return
|
|
||||||
// data structures that do not need to be converted in order to pass to Bullet.
|
|
||||||
// And maybe put the values directly into pinned memory rather than marshaling.
|
|
||||||
int hullCount = m_hulls.Count;
|
|
||||||
int totalVertices = 1; // include one for the count of the hulls
|
|
||||||
foreach (ConvexResult cr in m_hulls)
|
|
||||||
{
|
|
||||||
totalVertices += 4; // add four for the vertex count and centroid
|
|
||||||
totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
|
|
||||||
}
|
|
||||||
float[] convHulls = new float[totalVertices];
|
|
||||||
|
|
||||||
convHulls[0] = (float)hullCount;
|
|
||||||
int jj = 1;
|
|
||||||
foreach (ConvexResult cr in m_hulls)
|
|
||||||
{
|
|
||||||
// copy vertices for index access
|
|
||||||
float3[] verts = new float3[cr.HullVertices.Count];
|
|
||||||
int kk = 0;
|
|
||||||
foreach (float3 ff in cr.HullVertices)
|
|
||||||
{
|
{
|
||||||
verts[kk++] = ff;
|
convIndices.Add(indices[ii]);
|
||||||
|
}
|
||||||
|
foreach (OMV.Vector3 vv in vertices)
|
||||||
|
{
|
||||||
|
convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
|
||||||
}
|
}
|
||||||
|
|
||||||
// add to the array one hull's worth of data
|
// setup and do convex hull conversion
|
||||||
convHulls[jj++] = cr.HullIndices.Count;
|
m_hulls = new List<ConvexResult>();
|
||||||
convHulls[jj++] = 0f; // centroid x,y,z
|
DecompDesc dcomp = new DecompDesc();
|
||||||
convHulls[jj++] = 0f;
|
dcomp.mIndices = convIndices;
|
||||||
convHulls[jj++] = 0f;
|
dcomp.mVertices = convVertices;
|
||||||
foreach (int ind in cr.HullIndices)
|
ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
|
||||||
|
// create the hull into the _hulls variable
|
||||||
|
convexBuilder.process(dcomp);
|
||||||
|
|
||||||
|
// Convert the vertices and indices for passing to unmanaged.
|
||||||
|
// The hull information is passed as a large floating point array.
|
||||||
|
// The format is:
|
||||||
|
// convHulls[0] = number of hulls
|
||||||
|
// convHulls[1] = number of vertices in first hull
|
||||||
|
// convHulls[2] = hull centroid X coordinate
|
||||||
|
// convHulls[3] = hull centroid Y coordinate
|
||||||
|
// convHulls[4] = hull centroid Z coordinate
|
||||||
|
// convHulls[5] = first hull vertex X
|
||||||
|
// convHulls[6] = first hull vertex Y
|
||||||
|
// convHulls[7] = first hull vertex Z
|
||||||
|
// convHulls[8] = second hull vertex X
|
||||||
|
// ...
|
||||||
|
// convHulls[n] = number of vertices in second hull
|
||||||
|
// convHulls[n+1] = second hull centroid X coordinate
|
||||||
|
// ...
|
||||||
|
//
|
||||||
|
// TODO: is is very inefficient. Someday change the convex hull generator to return
|
||||||
|
// data structures that do not need to be converted in order to pass to Bullet.
|
||||||
|
// And maybe put the values directly into pinned memory rather than marshaling.
|
||||||
|
int hullCount = m_hulls.Count;
|
||||||
|
int totalVertices = 1; // include one for the count of the hulls
|
||||||
|
foreach (ConvexResult cr in m_hulls)
|
||||||
{
|
{
|
||||||
convHulls[jj++] = verts[ind].x;
|
totalVertices += 4; // add four for the vertex count and centroid
|
||||||
convHulls[jj++] = verts[ind].y;
|
totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
|
||||||
convHulls[jj++] = verts[ind].z;
|
|
||||||
}
|
}
|
||||||
|
float[] convHulls = new float[totalVertices];
|
||||||
|
|
||||||
|
convHulls[0] = (float)hullCount;
|
||||||
|
int jj = 1;
|
||||||
|
foreach (ConvexResult cr in m_hulls)
|
||||||
|
{
|
||||||
|
// copy vertices for index access
|
||||||
|
float3[] verts = new float3[cr.HullVertices.Count];
|
||||||
|
int kk = 0;
|
||||||
|
foreach (float3 ff in cr.HullVertices)
|
||||||
|
{
|
||||||
|
verts[kk++] = ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add to the array one hull's worth of data
|
||||||
|
convHulls[jj++] = cr.HullIndices.Count;
|
||||||
|
convHulls[jj++] = 0f; // centroid x,y,z
|
||||||
|
convHulls[jj++] = 0f;
|
||||||
|
convHulls[jj++] = 0f;
|
||||||
|
foreach (int ind in cr.HullIndices)
|
||||||
|
{
|
||||||
|
convHulls[jj++] = verts[ind].x;
|
||||||
|
convHulls[jj++] = verts[ind].y;
|
||||||
|
convHulls[jj++] = verts[ind].z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// create the hull data structure in Bullet
|
||||||
|
hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls);
|
||||||
}
|
}
|
||||||
// create the hull data structure in Bullet
|
|
||||||
hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL);
|
BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL);
|
||||||
|
@ -676,6 +698,50 @@ public class BSShapeCollection : IDisposable
|
||||||
return ComputeShapeKey(shapeData, pbs, out lod);
|
return ComputeShapeKey(shapeData, pbs, out lod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs)
|
||||||
|
{
|
||||||
|
// If the shape was successfully created, nothing more to do
|
||||||
|
if (newShape.ptr != IntPtr.Zero)
|
||||||
|
return newShape;
|
||||||
|
|
||||||
|
// The most common reason for failure is that an underlying asset is not available
|
||||||
|
|
||||||
|
// If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
|
||||||
|
if (pbs.SculptEntry && !prim.LastAssetBuildFailed && pbs.SculptTexture != OMV.UUID.Zero)
|
||||||
|
{
|
||||||
|
prim.LastAssetBuildFailed = true;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (!yprim.BaseShape.SculptEntry)
|
||||||
|
return;
|
||||||
|
if (yprim.BaseShape.SculptTexture.ToString() != asset.ID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
yprim.BaseShape.SculptData = new byte[asset.Data.Length];
|
||||||
|
asset.Data.CopyTo(yprim.BaseShape.SculptData, 0);
|
||||||
|
// This will cause the prim to see that the filler shape is not the right
|
||||||
|
// one and try again to build the object.
|
||||||
|
yprim.ForceBodyShapeRebuild(false);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// While we figure out the real problem, stick a simple native shape on the object.
|
||||||
|
BulletShape fillinShape =
|
||||||
|
BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_SPHERE, shapeData, ShapeData.FixedShapeKey.KEY_SPHERE);
|
||||||
|
|
||||||
|
return fillinShape;
|
||||||
|
}
|
||||||
|
|
||||||
// Create a body object in Bullet.
|
// Create a body object in Bullet.
|
||||||
// Updates prim.BSBody with the information about the new body if one is created.
|
// Updates prim.BSBody with the information about the new body if one is created.
|
||||||
// Returns 'true' if an object was actually created.
|
// Returns 'true' if an object was actually created.
|
||||||
|
|
Loading…
Reference in New Issue