BulletSim: move center of gravity of linkset to its geometric center.
Necessitated allowing simulator and physical position of a body to get out of sync since Bullet assumes that <0,0,0> is the center of mass. Update DLLs and SOs for the UpdateChildTransform so positions of individual prim in a linkset can be implemented.user_profiles
parent
eacc2561d1
commit
459fcd81c9
|
@ -327,6 +327,12 @@ public override void RemoveChildShapeFromCompoundShape(BulletShape shape, Bullet
|
|||
BSAPICPP.RemoveChildShapeFromCompoundShape2(shapeu.ptr, removeShapeu.ptr);
|
||||
}
|
||||
|
||||
public override void UpdateChildTransform(BulletShape pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb)
|
||||
{
|
||||
BulletShapeUnman shapeu = pShape as BulletShapeUnman;
|
||||
BSAPICPP.UpdateChildTransform2(shapeu.ptr, childIndex, pos, rot, shouldRecalculateLocalAabb);
|
||||
}
|
||||
|
||||
public override void RecalculateCompoundShapeLocalAabb(BulletShape shape)
|
||||
{
|
||||
BulletShapeUnman shapeu = shape as BulletShapeUnman;
|
||||
|
@ -1356,6 +1362,9 @@ public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShap
|
|||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void UpdateChildTransform2(IntPtr pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void RecalculateCompoundShapeLocalAabb2(IntPtr cShape);
|
||||
|
||||
|
|
|
@ -1212,6 +1212,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
|
|||
|
||||
public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) { /* TODO */ return null; }
|
||||
public override void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape) { /* TODO */ }
|
||||
public override void UpdateChildTransform(BulletShape pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb) { /* TODO */ }
|
||||
|
||||
public override BulletShape CreateGroundPlaneShape(uint pLocalId, float pheight, float pcollisionMargin)
|
||||
{
|
||||
|
|
|
@ -342,6 +342,8 @@ public abstract BulletShape RemoveChildShapeFromCompoundShapeIndex(BulletShape c
|
|||
|
||||
public abstract void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape);
|
||||
|
||||
public abstract void UpdateChildTransform(BulletShape pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb);
|
||||
|
||||
public abstract void RecalculateCompoundShapeLocalAabb(BulletShape cShape);
|
||||
|
||||
public abstract BulletShape DuplicateCollisionShape(BulletWorld sim, BulletShape srcShape, uint id);
|
||||
|
|
|
@ -148,7 +148,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
enableAngularVerticalAttraction = false;
|
||||
enableAngularDeflection = false;
|
||||
enableAngularBanking = false;
|
||||
VDetailLog("{0},BSDynamics.SetupVehicleDebugging,settingDebugMode", Prim.LocalID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -690,10 +689,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
}
|
||||
|
||||
if ((m_knownChanged & m_knownChangedForce) != 0)
|
||||
Prim.AddForce((Vector3)m_knownForce, false, true);
|
||||
Prim.AddForce((Vector3)m_knownForce, false /*pushForce*/, true /*inTaintTime*/);
|
||||
|
||||
if ((m_knownChanged & m_knownChangedForceImpulse) != 0)
|
||||
Prim.AddForceImpulse((Vector3)m_knownForceImpulse, false, true);
|
||||
Prim.AddForceImpulse((Vector3)m_knownForceImpulse, false /*pushforce*/, true /*inTaintTime*/);
|
||||
|
||||
if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0)
|
||||
{
|
||||
|
@ -703,7 +702,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
|
||||
if ((m_knownChanged & m_knownChangedRotationalForce) != 0)
|
||||
{
|
||||
Prim.AddAngularForce((Vector3)m_knownRotationalForce, false, true);
|
||||
Prim.AddAngularForce((Vector3)m_knownRotationalForce, false /*pushForce*/, true /*inTaintTime*/);
|
||||
}
|
||||
|
||||
// If we set one of the values (ie, the physics engine didn't do it) we must force
|
||||
|
@ -970,7 +969,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
// Act against the inertia of the vehicle
|
||||
linearMotorForce *= m_vehicleMass;
|
||||
|
||||
VehicleAddForceImpulse(linearMotorForce);
|
||||
VehicleAddForceImpulse(linearMotorForce * pTimestep);
|
||||
|
||||
VDetailLog("{0}, MoveLinear,velocity,vehVel={1},step={2},stepVel={3},mix={4},force={5}",
|
||||
Prim.LocalID, VehicleVelocity, linearMotorStep, linearMotorVelocity, mixFactor, linearMotorForce);
|
||||
|
@ -1033,7 +1032,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
{
|
||||
// Error is positive if below the target and negative if above.
|
||||
float verticalError = m_VhoverTargetHeight - VehiclePosition.Z;
|
||||
float verticalCorrectionVelocity = verticalError / m_VhoverTimescale;
|
||||
float verticalCorrectionVelocity = verticalError / m_VhoverTimescale * pTimestep;
|
||||
|
||||
// TODO: implement m_VhoverEfficiency correctly
|
||||
VehicleAddForceImpulse(new Vector3(0f, 0f, verticalCorrectionVelocity));
|
||||
|
@ -1323,7 +1322,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
// this creates an over-correction and then wabbling as the target is overshot.
|
||||
// TODO: rethink how the different correction computations inter-relate.
|
||||
|
||||
if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleVelocity != Vector3.Zero)
|
||||
if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2)
|
||||
{
|
||||
// The direction the vehicle is moving
|
||||
Vector3 movingDirection = VehicleVelocity;
|
||||
|
|
|
@ -152,6 +152,7 @@ public abstract class BSLinkset
|
|||
if (IsRoot(child))
|
||||
{
|
||||
// Cannot remove the root from a linkset.
|
||||
child.PositionDisplacement = OMV.Vector3.Zero;
|
||||
return this;
|
||||
}
|
||||
RemoveChildFromLinkset(child);
|
||||
|
@ -159,6 +160,7 @@ public abstract class BSLinkset
|
|||
}
|
||||
|
||||
// The child is down to a linkset of just itself
|
||||
child.PositionDisplacement = OMV.Vector3.Zero;
|
||||
return BSLinkset.Factory(PhysicsScene, child);
|
||||
}
|
||||
|
||||
|
@ -310,7 +312,7 @@ public abstract class BSLinkset
|
|||
|
||||
foreach (BSPhysObject bp in m_children)
|
||||
{
|
||||
com += bp.Position * bp.RawMass;
|
||||
com += bp.Position;
|
||||
}
|
||||
com /= (m_children.Count + 1);
|
||||
}
|
||||
|
|
|
@ -40,23 +40,33 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
// removed from the linkset.
|
||||
sealed class BSLinksetCompoundInfo : BSLinksetInfo
|
||||
{
|
||||
public OMV.Vector3 OffsetPos;
|
||||
public int Index;
|
||||
public OMV.Vector3 OffsetFromRoot;
|
||||
public OMV.Vector3 OffsetFromCenterOfMass;
|
||||
public OMV.Quaternion OffsetRot;
|
||||
public BSLinksetCompoundInfo(OMV.Vector3 p, OMV.Quaternion r)
|
||||
public BSLinksetCompoundInfo(int indx, OMV.Vector3 p, OMV.Quaternion r)
|
||||
{
|
||||
OffsetPos = p;
|
||||
Index = indx;
|
||||
OffsetFromRoot = p;
|
||||
OffsetFromCenterOfMass = p;
|
||||
OffsetRot = r;
|
||||
}
|
||||
public override void Clear()
|
||||
{
|
||||
OffsetPos = OMV.Vector3.Zero;
|
||||
Index = 0;
|
||||
OffsetFromRoot = OMV.Vector3.Zero;
|
||||
OffsetFromCenterOfMass = OMV.Vector3.Zero;
|
||||
OffsetRot = OMV.Quaternion.Identity;
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder buff = new StringBuilder();
|
||||
buff.Append("<p=");
|
||||
buff.Append(OffsetPos.ToString());
|
||||
buff.Append("<i=");
|
||||
buff.Append(Index.ToString());
|
||||
buff.Append(",p=");
|
||||
buff.Append(OffsetFromRoot.ToString());
|
||||
buff.Append(",m=");
|
||||
buff.Append(OffsetFromCenterOfMass.ToString());
|
||||
buff.Append(",r=");
|
||||
buff.Append(OffsetRot.ToString());
|
||||
buff.Append(">");
|
||||
|
@ -170,6 +180,8 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
return ret;
|
||||
}
|
||||
|
||||
// 'physicalUpdate' is true if these changes came directly from the physics engine. Don't need to rebuild then.
|
||||
// Called at taint-time.
|
||||
public override void UpdateProperties(BSPhysObject updated, bool physicalUpdate)
|
||||
{
|
||||
// The user moving a child around requires the rebuilding of the linkset compound shape
|
||||
|
@ -182,6 +194,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
&& !physicalUpdate
|
||||
&& PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition))
|
||||
{
|
||||
// TODO: replace this with are calculation of the child prim's orientation and pos.
|
||||
updated.LinksetInfo = null;
|
||||
ScheduleRebuild(updated);
|
||||
}
|
||||
|
@ -230,7 +243,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
if (inTaintTime)
|
||||
{
|
||||
OMV.Vector3 oldPos = child.RawPosition;
|
||||
child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetPos;
|
||||
child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetFromRoot;
|
||||
child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot;
|
||||
DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}",
|
||||
child.LocalID, oldPos, lci, child.RawPosition);
|
||||
|
@ -238,7 +251,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
else
|
||||
{
|
||||
// TaintedObject is not used here so the raw position is set now and not at taint-time.
|
||||
child.Position = LinksetRoot.RawPosition + lci.OffsetPos;
|
||||
child.Position = LinksetRoot.RawPosition + lci.OffsetFromRoot;
|
||||
child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot;
|
||||
}
|
||||
}
|
||||
|
@ -316,10 +329,23 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
// Cause the root shape to be rebuilt as a compound object with just the root in it
|
||||
LinksetRoot.ForceBodyShapeRebuild(true);
|
||||
|
||||
// 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.
|
||||
OMV.Vector3 centerOfMass = ComputeLinksetGeometricCenter();
|
||||
OMV.Vector3 centerDisplacement = centerOfMass - LinksetRoot.RawPosition;
|
||||
|
||||
// Since we're displacing the center of the shape, we need to move the body in the world
|
||||
LinksetRoot.PositionDisplacement = centerDisplacement * LinksetRoot.RawOrientation;
|
||||
|
||||
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0, -centerDisplacement, OMV.Quaternion.Identity, false);
|
||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
|
||||
LinksetRoot.LocalID, centerOfMass, LinksetRoot.RawPosition, centerDisplacement);
|
||||
|
||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
|
||||
LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
|
||||
|
||||
// Add a shape for each of the other children in the linkset
|
||||
int memberIndex = 1;
|
||||
ForEachMember(delegate(BSPhysObject cPrim)
|
||||
{
|
||||
if (!IsRoot(cPrim))
|
||||
|
@ -337,13 +363,14 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
|
||||
|
||||
// Save relative position for recomputing child's world position after moving linkset.
|
||||
lci = new BSLinksetCompoundInfo(displacementPos, displacementRot);
|
||||
lci = new BSLinksetCompoundInfo(memberIndex, displacementPos, displacementRot);
|
||||
lci.OffsetFromCenterOfMass = displacementPos - centerDisplacement;
|
||||
cPrim.LinksetInfo = lci;
|
||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci);
|
||||
}
|
||||
|
||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}",
|
||||
LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot);
|
||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},lci={3}",
|
||||
LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci);
|
||||
|
||||
if (cPrim.PhysShape.isNativeShape)
|
||||
{
|
||||
|
@ -359,7 +386,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
|
||||
BulletShape newShape = cPrim.PhysShape;
|
||||
cPrim.PhysShape = saveShape;
|
||||
PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetPos, lci.OffsetRot);
|
||||
PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetFromCenterOfMass, lci.OffsetRot);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -371,8 +398,10 @@ public sealed class BSLinksetCompound : BSLinkset
|
|||
PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
|
||||
LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
|
||||
}
|
||||
PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot);
|
||||
PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetFromCenterOfMass, lci.OffsetRot);
|
||||
}
|
||||
lci.Index = memberIndex;
|
||||
memberIndex++;
|
||||
}
|
||||
return false; // 'false' says to move onto the next child in the list
|
||||
});
|
||||
|
|
|
@ -73,6 +73,8 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
|
||||
// A linkset of just me
|
||||
Linkset = BSLinkset.Factory(PhysicsScene, this);
|
||||
PositionDisplacement = OMV.Vector3.Zero;
|
||||
|
||||
LastAssetBuildFailed = false;
|
||||
|
||||
// Default material type
|
||||
|
@ -157,6 +159,14 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
public abstract OMV.Vector3 RawPosition { get; set; }
|
||||
public abstract OMV.Vector3 ForcePosition { get; set; }
|
||||
|
||||
// Position is what the simulator thinks the positions of the prim is.
|
||||
// Because Bullet needs the zero coordinate to be the center of mass of the linkset,
|
||||
// sometimes it is necessary to displace the position the physics engine thinks
|
||||
// the position is. PositionDisplacement must be added and removed from the
|
||||
// position as the simulator position is stored and fetched from the physics
|
||||
// engine.
|
||||
public virtual OMV.Vector3 PositionDisplacement { get; set; }
|
||||
|
||||
public abstract OMV.Quaternion RawOrientation { get; set; }
|
||||
public abstract OMV.Quaternion ForceOrientation { get; set; }
|
||||
|
||||
|
|
|
@ -50,7 +50,10 @@ public sealed class BSPrim : BSPhysObject
|
|||
private bool _grabbed;
|
||||
private bool _isSelected;
|
||||
private bool _isVolumeDetect;
|
||||
|
||||
// _position is what the simulator thinks the positions of the prim is.
|
||||
private OMV.Vector3 _position;
|
||||
|
||||
private float _mass; // the mass of this object
|
||||
private float _density;
|
||||
private OMV.Vector3 _force;
|
||||
|
@ -320,18 +323,37 @@ public sealed class BSPrim : BSPhysObject
|
|||
}
|
||||
public override OMV.Vector3 ForcePosition {
|
||||
get {
|
||||
_position = PhysicsScene.PE.GetPosition(PhysBody);
|
||||
_position = PhysicsScene.PE.GetPosition(PhysBody) - PositionDisplacement;
|
||||
return _position;
|
||||
}
|
||||
set {
|
||||
_position = value;
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
{
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
|
||||
ActivateIfPhysical(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Override to have position displacement immediately update the physical position.
|
||||
// A feeble attempt to keep the sim and physical positions in sync
|
||||
// Must be called at taint time.
|
||||
public override OMV.Vector3 PositionDisplacement
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.PositionDisplacement;
|
||||
}
|
||||
set
|
||||
{
|
||||
base.PositionDisplacement = value;
|
||||
PhysicsScene.TaintedObject(PhysicsScene.InTaintTime, "BSPrim.setPosition", delegate()
|
||||
{
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position + base.PositionDisplacement, _orientation);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the current position is sane and, if not, modify the position to make it so.
|
||||
// Check for being below terrain and being out of bounds.
|
||||
|
@ -590,6 +612,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
_velocity = value;
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
{
|
||||
DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, _velocity);
|
||||
PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity);
|
||||
ActivateIfPhysical(false);
|
||||
}
|
||||
|
@ -654,12 +677,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
|
||||
PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
|
||||
{
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
{
|
||||
// _position = PhysicsScene.PE.GetObjectPosition(PhysicsScene.World, BSBody);
|
||||
// DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
|
||||
}
|
||||
ForceOrientation = _orientation;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -674,7 +692,8 @@ public sealed class BSPrim : BSPhysObject
|
|||
set
|
||||
{
|
||||
_orientation = value;
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
|
||||
}
|
||||
}
|
||||
public override int PhysicsActorType {
|
||||
|
@ -813,7 +832,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
// PhysicsScene.PE.ClearAllForces(BSBody);
|
||||
|
||||
// For good measure, make sure the transform is set through to the motion state
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
|
||||
|
||||
// Center of mass is at the center of the object
|
||||
// DEBUG DEBUG PhysicsScene.PE.SetCenterOfMassByPosRot(Linkset.LinksetRoot.PhysBody, _position, _orientation);
|
||||
|
@ -1615,6 +1634,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
}
|
||||
|
||||
// Assign directly to the local variables so the normal set actions do not happen
|
||||
entprop.Position -= PositionDisplacement;
|
||||
_position = entprop.Position;
|
||||
_orientation = entprop.Rotation;
|
||||
_velocity = entprop.Velocity;
|
||||
|
|
|
@ -906,7 +906,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
// While we figure out the real problem, stick a simple native shape on the object.
|
||||
// While we figure out the real problem, stick in a simple box for the object.
|
||||
BulletShape fillinShape =
|
||||
BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
|
||||
|
||||
|
|
|
@ -170,6 +170,8 @@ Avatar attachments have no mass? http://forums-archive.secondlife.com/54/f0/3179
|
|||
|
||||
INTERNAL IMPROVEMENT/CLEANUP
|
||||
=================================================
|
||||
Can the 'inTaintTime' flag be cleaned up and used? For instance, a call to
|
||||
BSScene.TaintedObject() could immediately execute the callback if already in taint time.
|
||||
Create the physical wrapper classes (BulletBody, BulletShape) by methods on
|
||||
BSAPITemplate and make their actual implementation Bullet engine specific.
|
||||
For the short term, just call the existing functions in ShapeCollection.
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue