* Merges BulletSim Updates to BulletSimN(BulletSNPlugin)
parent
225b564573
commit
29cdf0f3dd
|
@ -174,7 +174,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, BSParam.CcdSweptSphereRadius);
|
BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, BSParam.CcdSweptSphereRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdatePhysicalMassProperties(RawMass);
|
UpdatePhysicalMassProperties(RawMass, false);
|
||||||
|
|
||||||
// Make so capsule does not fall over
|
// Make so capsule does not fall over
|
||||||
BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero);
|
BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero);
|
||||||
|
@ -224,7 +224,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape)
|
if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape)
|
||||||
{
|
{
|
||||||
BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale);
|
BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale);
|
||||||
UpdatePhysicalMassProperties(RawMass);
|
UpdatePhysicalMassProperties(RawMass, true);
|
||||||
// Make sure this change appears as a property update event
|
// Make sure this change appears as a property update event
|
||||||
BulletSimAPI.PushUpdate2(PhysBody.ptr);
|
BulletSimAPI.PushUpdate2(PhysBody.ptr);
|
||||||
}
|
}
|
||||||
|
@ -260,7 +260,6 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
public override void ZeroMotion(bool inTaintTime)
|
public override void ZeroMotion(bool inTaintTime)
|
||||||
{
|
{
|
||||||
_velocity = OMV.Vector3.Zero;
|
_velocity = OMV.Vector3.Zero;
|
||||||
_velocityMotor.Zero();
|
|
||||||
_acceleration = OMV.Vector3.Zero;
|
_acceleration = OMV.Vector3.Zero;
|
||||||
_rotationalVelocity = OMV.Vector3.Zero;
|
_rotationalVelocity = OMV.Vector3.Zero;
|
||||||
|
|
||||||
|
@ -390,7 +389,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
public override float RawMass {
|
public override float RawMass {
|
||||||
get {return _mass; }
|
get {return _mass; }
|
||||||
}
|
}
|
||||||
public override void UpdatePhysicalMassProperties(float physMass)
|
public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
|
||||||
{
|
{
|
||||||
OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
|
OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
|
||||||
BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia);
|
BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia);
|
||||||
|
@ -787,6 +786,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
// the motor can be turned off. Set the velocity to zero so the zero motion is sent to the viewer.
|
// the motor can be turned off. Set the velocity to zero so the zero motion is sent to the viewer.
|
||||||
if (_velocityMotor.TargetValue.ApproxEquals(OMV.Vector3.Zero, 0.01f) && _velocityMotor.ErrorIsZero)
|
if (_velocityMotor.TargetValue.ApproxEquals(OMV.Vector3.Zero, 0.01f) && _velocityMotor.ErrorIsZero)
|
||||||
{
|
{
|
||||||
|
ZeroMotion(true);
|
||||||
stepVelocity = OMV.Vector3.Zero;
|
stepVelocity = OMV.Vector3.Zero;
|
||||||
_velocityMotor.Enabled = false;
|
_velocityMotor.Enabled = false;
|
||||||
DetailLog("{0},BSCharacter.UpdateProperties,taint,disableVelocityMotor,m={1}", LocalID, _velocityMotor);
|
DetailLog("{0},BSCharacter.UpdateProperties,taint,disableVelocityMotor,m={1}", LocalID, _velocityMotor);
|
||||||
|
|
|
@ -36,7 +36,7 @@ public abstract class BSConstraint : IDisposable
|
||||||
{
|
{
|
||||||
private static string LogHeader = "[BULLETSIM CONSTRAINT]";
|
private static string LogHeader = "[BULLETSIM CONSTRAINT]";
|
||||||
|
|
||||||
protected BulletSim m_world;
|
protected BulletWorld m_world;
|
||||||
protected BulletBody m_body1;
|
protected BulletBody m_body1;
|
||||||
protected BulletBody m_body2;
|
protected BulletBody m_body2;
|
||||||
protected BulletConstraint m_constraint;
|
protected BulletConstraint m_constraint;
|
||||||
|
|
|
@ -39,7 +39,7 @@ public sealed class BSConstraint6Dof : BSConstraint
|
||||||
public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } }
|
public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } }
|
||||||
|
|
||||||
// Create a btGeneric6DofConstraint
|
// Create a btGeneric6DofConstraint
|
||||||
public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2,
|
public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
Vector3 frame1, Quaternion frame1rot,
|
Vector3 frame1, Quaternion frame1rot,
|
||||||
Vector3 frame2, Quaternion frame2rot,
|
Vector3 frame2, Quaternion frame2rot,
|
||||||
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
|
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
|
||||||
|
@ -58,7 +58,7 @@ public sealed class BSConstraint6Dof : BSConstraint
|
||||||
obj1.ID, obj1.ptr.ToString(), obj2.ID, obj2.ptr.ToString());
|
obj1.ID, obj1.ptr.ToString(), obj2.ID, obj2.ptr.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2,
|
public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
Vector3 joinPoint,
|
Vector3 joinPoint,
|
||||||
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
|
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
|
||||||
{
|
{
|
||||||
|
|
|
@ -41,9 +41,9 @@ public sealed class BSConstraintCollection : IDisposable
|
||||||
delegate bool ConstraintAction(BSConstraint constrain);
|
delegate bool ConstraintAction(BSConstraint constrain);
|
||||||
|
|
||||||
private List<BSConstraint> m_constraints;
|
private List<BSConstraint> m_constraints;
|
||||||
private BulletSim m_world;
|
private BulletWorld m_world;
|
||||||
|
|
||||||
public BSConstraintCollection(BulletSim world)
|
public BSConstraintCollection(BulletWorld world)
|
||||||
{
|
{
|
||||||
m_world = world;
|
m_world = world;
|
||||||
m_constraints = new List<BSConstraint>();
|
m_constraints = new List<BSConstraint>();
|
||||||
|
|
|
@ -36,7 +36,7 @@ public sealed class BSConstraintHinge : BSConstraint
|
||||||
{
|
{
|
||||||
public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } }
|
public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } }
|
||||||
|
|
||||||
public BSConstraintHinge(BulletSim world, BulletBody obj1, BulletBody obj2,
|
public BSConstraintHinge(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
Vector3 pivotInA, Vector3 pivotInB,
|
Vector3 pivotInA, Vector3 pivotInB,
|
||||||
Vector3 axisInA, Vector3 axisInB,
|
Vector3 axisInA, Vector3 axisInB,
|
||||||
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
|
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
|
||||||
|
|
|
@ -573,6 +573,9 @@ namespace OpenSim.Region.Physics.BulletSNPlugin
|
||||||
BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
|
BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
|
||||||
BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr);
|
BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr);
|
||||||
|
|
||||||
|
Vector3 grav = PhysicsScene.DefaultGravity * (1f - Prim.Buoyancy);
|
||||||
|
BulletSimAPI.SetGravity2(Prim.PhysBody.ptr, grav);
|
||||||
|
|
||||||
VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}",
|
VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}",
|
||||||
Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping);
|
Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping);
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,14 +97,7 @@ public abstract class BSLinkset
|
||||||
}
|
}
|
||||||
|
|
||||||
// We keep the prim's mass in the linkset structure since it could be dependent on other prims
|
// We keep the prim's mass in the linkset structure since it could be dependent on other prims
|
||||||
protected float m_mass;
|
public float LinksetMass { get; protected set; }
|
||||||
public float LinksetMass
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return m_mass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool LinksetIsColliding { get { return false; } }
|
public virtual bool LinksetIsColliding { get { return false; } }
|
||||||
|
|
||||||
|
@ -128,7 +121,7 @@ public abstract class BSLinkset
|
||||||
PhysicsScene = scene;
|
PhysicsScene = scene;
|
||||||
LinksetRoot = parent;
|
LinksetRoot = parent;
|
||||||
m_children = new HashSet<BSPhysObject>();
|
m_children = new HashSet<BSPhysObject>();
|
||||||
m_mass = parent.RawMass;
|
LinksetMass = parent.RawMass;
|
||||||
Rebuilding = false;
|
Rebuilding = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +136,7 @@ public abstract class BSLinkset
|
||||||
// Don't add the root to its own linkset
|
// Don't add the root to its own linkset
|
||||||
if (!IsRoot(child))
|
if (!IsRoot(child))
|
||||||
AddChildToLinkset(child);
|
AddChildToLinkset(child);
|
||||||
m_mass = ComputeLinksetMass();
|
LinksetMass = ComputeLinksetMass();
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +155,7 @@ public abstract class BSLinkset
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
RemoveChildFromLinkset(child);
|
RemoveChildFromLinkset(child);
|
||||||
m_mass = ComputeLinksetMass();
|
LinksetMass = ComputeLinksetMass();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The child is down to a linkset of just itself
|
// The child is down to a linkset of just itself
|
||||||
|
@ -230,7 +223,10 @@ public abstract class BSLinkset
|
||||||
// When physical properties are changed the linkset needs to recalculate
|
// When physical properties are changed the linkset needs to recalculate
|
||||||
// its internal properties.
|
// its internal properties.
|
||||||
// May be called at runtime or taint-time.
|
// May be called at runtime or taint-time.
|
||||||
public abstract void Refresh(BSPhysObject requestor);
|
public virtual void Refresh(BSPhysObject requestor)
|
||||||
|
{
|
||||||
|
LinksetMass = ComputeLinksetMass();
|
||||||
|
}
|
||||||
|
|
||||||
// Flag denoting the linkset is in the process of being rebuilt.
|
// Flag denoting the linkset is in the process of being rebuilt.
|
||||||
// Used to know not the schedule a rebuild in the middle of a rebuild.
|
// Used to know not the schedule a rebuild in the middle of a rebuild.
|
||||||
|
|
|
@ -89,6 +89,8 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
// its internal properties.
|
// its internal properties.
|
||||||
public override void Refresh(BSPhysObject requestor)
|
public override void Refresh(BSPhysObject requestor)
|
||||||
{
|
{
|
||||||
|
base.Refresh(requestor);
|
||||||
|
|
||||||
// Something changed so do the rebuilding thing
|
// Something changed so do the rebuilding thing
|
||||||
// ScheduleRebuild();
|
// ScheduleRebuild();
|
||||||
}
|
}
|
||||||
|
@ -96,13 +98,13 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
// Schedule a refresh to happen after all the other taint processing.
|
// Schedule a refresh to happen after all the other taint processing.
|
||||||
private void ScheduleRebuild(BSPhysObject requestor)
|
private void ScheduleRebuild(BSPhysObject requestor)
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,rebuilding={1}",
|
DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1}",
|
||||||
requestor.LocalID, Rebuilding);
|
requestor.LocalID, Rebuilding);
|
||||||
// When rebuilding, it is possible to set properties that would normally require a rebuild.
|
// When rebuilding, it is possible to set properties that would normally require a rebuild.
|
||||||
// If already rebuilding, don't request another rebuild.
|
// If already rebuilding, don't request another rebuild.
|
||||||
if (!Rebuilding)
|
if (!Rebuilding)
|
||||||
{
|
{
|
||||||
PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", LinksetRoot.LocalID, delegate()
|
PhysicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate()
|
||||||
{
|
{
|
||||||
if (HasAnyChildren)
|
if (HasAnyChildren)
|
||||||
RecomputeLinksetCompound();
|
RecomputeLinksetCompound();
|
||||||
|
@ -123,7 +125,6 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
if (IsRoot(child))
|
if (IsRoot(child))
|
||||||
{
|
{
|
||||||
// The root is going dynamic. Make sure mass is properly set.
|
// The root is going dynamic. Make sure mass is properly set.
|
||||||
m_mass = ComputeLinksetMass();
|
|
||||||
ScheduleRebuild(LinksetRoot);
|
ScheduleRebuild(LinksetRoot);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -377,8 +378,8 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
});
|
});
|
||||||
|
|
||||||
// With all of the linkset packed into the root prim, it has the mass of everyone.
|
// With all of the linkset packed into the root prim, it has the mass of everyone.
|
||||||
float linksetMass = LinksetMass;
|
LinksetMass = LinksetMass;
|
||||||
LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
|
LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,6 +46,8 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||||
// refresh will happen once after all the other taints are applied.
|
// refresh will happen once after all the other taints are applied.
|
||||||
public override void Refresh(BSPhysObject requestor)
|
public override void Refresh(BSPhysObject requestor)
|
||||||
{
|
{
|
||||||
|
base.Refresh(requestor);
|
||||||
|
|
||||||
// Queue to happen after all the other taint processing
|
// Queue to happen after all the other taint processing
|
||||||
PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
|
PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
|
||||||
{
|
{
|
||||||
|
@ -279,7 +281,7 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||||
private void RecomputeLinksetConstraints()
|
private void RecomputeLinksetConstraints()
|
||||||
{
|
{
|
||||||
float linksetMass = LinksetMass;
|
float linksetMass = LinksetMass;
|
||||||
LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
|
LinksetRoot.UpdatePhysicalMassProperties(linksetMass, true);
|
||||||
|
|
||||||
// DEBUG: see of inter-linkset collisions are causing problems
|
// DEBUG: see of inter-linkset collisions are causing problems
|
||||||
// BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr,
|
// BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr,
|
||||||
|
@ -292,7 +294,7 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||||
// A child in the linkset physically shows the mass of the whole linkset.
|
// A child in the linkset physically shows the mass of the whole linkset.
|
||||||
// This allows Bullet to apply enough force on the child to move the whole linkset.
|
// This allows Bullet to apply enough force on the child to move the whole linkset.
|
||||||
// (Also do the mass stuff before recomputing the constraint so mass is not zero.)
|
// (Also do the mass stuff before recomputing the constraint so mass is not zero.)
|
||||||
child.UpdatePhysicalMassProperties(linksetMass);
|
child.UpdatePhysicalMassProperties(linksetMass, true);
|
||||||
|
|
||||||
BSConstraint constrain;
|
BSConstraint constrain;
|
||||||
if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain))
|
if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain))
|
||||||
|
|
|
@ -119,26 +119,26 @@ public static class BSMaterials
|
||||||
Attributes[(int)MaterialAttributes.Material.Light] =
|
Attributes[(int)MaterialAttributes.Material.Light] =
|
||||||
new MaterialAttributes("light",dDensity, dFriction, dRestitution);
|
new MaterialAttributes("light",dDensity, dFriction, dRestitution);
|
||||||
Attributes[(int)MaterialAttributes.Material.Avatar] =
|
Attributes[(int)MaterialAttributes.Material.Avatar] =
|
||||||
new MaterialAttributes("avatar",60f, 0.2f, 0f);
|
new MaterialAttributes("avatar",3.5f, 0.2f, 0f);
|
||||||
|
|
||||||
Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] =
|
Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||||
new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f);
|
new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f);
|
||||||
Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] =
|
Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||||
new MaterialAttributes("metalPhysical",dDensity, 0.8f, 0.4f);
|
new MaterialAttributes("metalPhysical",dDensity, 0.3f, 0.4f);
|
||||||
Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] =
|
Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||||
new MaterialAttributes("glassPhysical",dDensity, 0.8f, 0.7f);
|
new MaterialAttributes("glassPhysical",dDensity, 0.2f, 0.7f);
|
||||||
Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] =
|
Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||||
new MaterialAttributes("woodPhysical",dDensity, 0.8f, 0.5f);
|
new MaterialAttributes("woodPhysical",dDensity, 0.6f, 0.5f);
|
||||||
Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] =
|
Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||||
new MaterialAttributes("fleshPhysical",dDensity, 0.8f, 0.3f);
|
new MaterialAttributes("fleshPhysical",dDensity, 0.9f, 0.3f);
|
||||||
Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] =
|
Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||||
new MaterialAttributes("plasticPhysical",dDensity, 0.8f, 0.7f);
|
new MaterialAttributes("plasticPhysical",dDensity, 0.4f, 0.7f);
|
||||||
Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] =
|
Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||||
new MaterialAttributes("rubberPhysical",dDensity, 0.8f, 0.9f);
|
new MaterialAttributes("rubberPhysical",dDensity, 0.9f, 0.9f);
|
||||||
Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] =
|
Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||||
new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution);
|
new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution);
|
||||||
Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] =
|
Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] =
|
||||||
new MaterialAttributes("avatarPhysical",60f, 0.2f, 0f);
|
new MaterialAttributes("avatarPhysical",3.5f, 0.2f, 0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Under the [BulletSim] section, one can change the individual material
|
// Under the [BulletSim] section, one can change the individual material
|
||||||
|
|
|
@ -351,7 +351,7 @@ public static class BSParam
|
||||||
(s) => { return AvatarStandingFriction; },
|
(s) => { return AvatarStandingFriction; },
|
||||||
(s,p,l,v) => { AvatarStandingFriction = v; } ),
|
(s,p,l,v) => { AvatarStandingFriction = v; } ),
|
||||||
new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
|
new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
|
||||||
60f,
|
3.5f,
|
||||||
(s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); },
|
||||||
(s) => { return AvatarDensity; },
|
(s) => { return AvatarDensity; },
|
||||||
(s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarDensity=x;}, p, l, v); } ),
|
(s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarDensity=x;}, p, l, v); } ),
|
||||||
|
|
|
@ -96,7 +96,8 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
// Return the object mass without calculating it or having side effects
|
// Return the object mass without calculating it or having side effects
|
||||||
public abstract float RawMass { get; }
|
public abstract float RawMass { get; }
|
||||||
// Set the raw mass but also update physical mass properties (inertia, ...)
|
// Set the raw mass but also update physical mass properties (inertia, ...)
|
||||||
public abstract void UpdatePhysicalMassProperties(float mass);
|
// 'inWorld' true if the object has already been added to the dynamic world.
|
||||||
|
public abstract void UpdatePhysicalMassProperties(float mass, bool inWorld);
|
||||||
|
|
||||||
// The last value calculated for the prim's inertia
|
// The last value calculated for the prim's inertia
|
||||||
public OMV.Vector3 Inertia { get; set; }
|
public OMV.Vector3 Inertia { get; set; }
|
||||||
|
|
|
@ -115,6 +115,8 @@ public sealed class BSPrim : BSPhysObject
|
||||||
PhysBody = new BulletBody(LocalID);
|
PhysBody = new BulletBody(LocalID);
|
||||||
PhysShape = new BulletShape();
|
PhysShape = new BulletShape();
|
||||||
|
|
||||||
|
Linkset.Refresh(this);
|
||||||
|
|
||||||
DetailLog("{0},BSPrim.constructor,call", LocalID);
|
DetailLog("{0},BSPrim.constructor,call", LocalID);
|
||||||
// do the actual object creation at taint time
|
// do the actual object creation at taint time
|
||||||
PhysicsScene.TaintedObject("BSPrim.create", delegate()
|
PhysicsScene.TaintedObject("BSPrim.create", delegate()
|
||||||
|
@ -384,13 +386,13 @@ public sealed class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the effective mass of the object.
|
// Return the effective mass of the object.
|
||||||
// If there are multiple items in the linkset, add them together for the root
|
// The definition of this call is to return the mass of the prim.
|
||||||
|
// If the simulator cares about the mass of the linkset, it will sum it itself.
|
||||||
public override float Mass
|
public override float Mass
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return Linkset.LinksetMass;
|
return _mass;
|
||||||
// return _mass;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,7 +402,9 @@ public sealed class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
// Set the physical mass to the passed mass.
|
// Set the physical mass to the passed mass.
|
||||||
// Note that this does not change _mass!
|
// Note that this does not change _mass!
|
||||||
public override void UpdatePhysicalMassProperties(float physMass)
|
public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
|
||||||
|
{
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
{
|
{
|
||||||
if (IsStatic)
|
if (IsStatic)
|
||||||
{
|
{
|
||||||
|
@ -410,12 +414,33 @@ public sealed class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (inWorld)
|
||||||
|
{
|
||||||
|
// Changing interesting properties doesn't change proxy and collision cache
|
||||||
|
// information. The Bullet solution is to re-add the object to the world
|
||||||
|
// after parameters are changed.
|
||||||
|
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
|
||||||
|
}
|
||||||
|
|
||||||
Inertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
|
Inertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
|
||||||
BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia);
|
BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia);
|
||||||
BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
|
BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
|
||||||
|
|
||||||
// center of mass is at the zero of the object
|
// center of mass is at the zero of the object
|
||||||
// DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation);
|
// DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation);
|
||||||
DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, Inertia);
|
DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},inWorld={3}", LocalID, physMass, Inertia, inWorld);
|
||||||
|
|
||||||
|
if (inWorld)
|
||||||
|
{
|
||||||
|
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr,_position,_orientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must set gravity after it has been added to the world because, for unknown reasons,
|
||||||
|
// adding the object resets the object's gravity to world gravity
|
||||||
|
OMV.Vector3 grav = PhysicsScene.DefaultGravity * (1f - Buoyancy);
|
||||||
|
BulletSimAPI.SetGravity2(PhysBody.ptr, grav);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -714,7 +739,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
Linkset.Refresh(this);
|
Linkset.Refresh(this);
|
||||||
|
|
||||||
DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}",
|
DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}",
|
||||||
LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape);
|
LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape);
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Making dynamic" means changing to and from static.
|
// "Making dynamic" means changing to and from static.
|
||||||
|
@ -737,7 +762,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
BulletSimAPI.SetRestitution2(PhysBody.ptr, matAttrib.restitution);
|
BulletSimAPI.SetRestitution2(PhysBody.ptr, matAttrib.restitution);
|
||||||
|
|
||||||
// Mass is zero which disables a bunch of physics stuff in Bullet
|
// Mass is zero which disables a bunch of physics stuff in Bullet
|
||||||
UpdatePhysicalMassProperties(0f);
|
UpdatePhysicalMassProperties(0f, false);
|
||||||
// Set collision detection parameters
|
// Set collision detection parameters
|
||||||
if (BSParam.CcdMotionThreshold > 0f)
|
if (BSParam.CcdMotionThreshold > 0f)
|
||||||
{
|
{
|
||||||
|
@ -777,7 +802,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
// DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
|
// DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
|
||||||
|
|
||||||
// A dynamic object has mass
|
// A dynamic object has mass
|
||||||
UpdatePhysicalMassProperties(RawMass);
|
UpdatePhysicalMassProperties(RawMass, false);
|
||||||
|
|
||||||
// Set collision detection parameters
|
// Set collision detection parameters
|
||||||
if (BSParam.CcdMotionThreshold > 0f)
|
if (BSParam.CcdMotionThreshold > 0f)
|
||||||
|
@ -950,15 +975,11 @@ public sealed class BSPrim : BSPhysObject
|
||||||
set {
|
set {
|
||||||
_buoyancy = value;
|
_buoyancy = value;
|
||||||
// DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
// DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
||||||
// Buoyancy is faked by changing the gravity applied to the object
|
// Force the recalculation of the various inertia,etc variables in the object
|
||||||
if (PhysBody.HasPhysicalBody)
|
UpdatePhysicalMassProperties(_mass, true);
|
||||||
{
|
|
||||||
float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
|
|
||||||
BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
|
|
||||||
ActivateIfPhysical(false);
|
ActivateIfPhysical(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Used for MoveTo
|
// Used for MoveTo
|
||||||
public override OMV.Vector3 PIDTarget {
|
public override OMV.Vector3 PIDTarget {
|
||||||
|
@ -993,7 +1014,9 @@ public sealed class BSPrim : BSPhysObject
|
||||||
public override float APIDDamping { set { return; } }
|
public override float APIDDamping { set { return; } }
|
||||||
|
|
||||||
public override void AddForce(OMV.Vector3 force, bool pushforce) {
|
public override void AddForce(OMV.Vector3 force, bool pushforce) {
|
||||||
AddForce(force, pushforce, false);
|
// Since this force is being applied in only one step, make this a force per second.
|
||||||
|
OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep;
|
||||||
|
AddForce(addForce, pushforce, false);
|
||||||
}
|
}
|
||||||
// Applying a force just adds this to the total force on the object.
|
// Applying a force just adds this to the total force on the object.
|
||||||
// This added force will only last the next simulation tick.
|
// This added force will only last the next simulation tick.
|
||||||
|
@ -1001,8 +1024,16 @@ public sealed class BSPrim : BSPhysObject
|
||||||
// for an object, doesn't matter if force is a pushforce or not
|
// for an object, doesn't matter if force is a pushforce or not
|
||||||
if (force.IsFinite())
|
if (force.IsFinite())
|
||||||
{
|
{
|
||||||
|
float magnitude = force.Length();
|
||||||
|
if (magnitude > 20000f)
|
||||||
|
{
|
||||||
|
// Force has a limit
|
||||||
|
force = force / magnitude * 20000f;
|
||||||
|
}
|
||||||
|
|
||||||
OMV.Vector3 addForce = force;
|
OMV.Vector3 addForce = force;
|
||||||
DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
|
DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
|
||||||
|
|
||||||
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
|
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
|
||||||
{
|
{
|
||||||
// Bullet adds this central force to the total force for this tick
|
// Bullet adds this central force to the total force for this tick
|
||||||
|
|
|
@ -74,7 +74,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
public IMesher mesher;
|
public IMesher mesher;
|
||||||
public uint WorldID { get; private set; }
|
public uint WorldID { get; private set; }
|
||||||
public BulletSim World { get; private set; }
|
public BulletWorld World { get; private set; }
|
||||||
|
|
||||||
// All the constraints that have been allocated in this instance.
|
// All the constraints that have been allocated in this instance.
|
||||||
public BSConstraintCollection Constraints { get; private set; }
|
public BSConstraintCollection Constraints { get; private set; }
|
||||||
|
@ -244,7 +244,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
// m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
|
// m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
|
||||||
|
|
||||||
World = new BulletSim(0, this, BulletSimAPI.Initialize2(worldExtent, UnmanagedParams,
|
World = new BulletWorld(0, this, BulletSimAPI.Initialize2(worldExtent, UnmanagedParams,
|
||||||
m_maxCollisionsPerFrame, ref m_collisionArray,
|
m_maxCollisionsPerFrame, ref m_collisionArray,
|
||||||
m_maxUpdatesPerFrame,ref m_updateArray,
|
m_maxUpdatesPerFrame,ref m_updateArray,
|
||||||
m_DebugLogCallbackHandle));
|
m_DebugLogCallbackHandle));
|
||||||
|
@ -497,13 +497,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
InTaintTime = false; // Only used for debugging so locking is not necessary.
|
InTaintTime = false; // Only used for debugging so locking is not necessary.
|
||||||
|
|
||||||
|
// The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
|
||||||
|
// Only enable this in a limited test world with few objects.
|
||||||
|
// BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG
|
||||||
|
|
||||||
// step the physical world one interval
|
// step the physical world one interval
|
||||||
m_simulationStep++;
|
m_simulationStep++;
|
||||||
int numSubSteps = 0;
|
int numSubSteps = 0;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
|
|
||||||
if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
|
if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
|
numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
|
||||||
|
@ -833,7 +836,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
|
DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
|
||||||
m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
|
m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
|
||||||
Util.PrintCallStack(); // Prints the stack into the DEBUG log file.
|
Util.PrintCallStack(DetailLog);
|
||||||
}
|
}
|
||||||
return InTaintTime;
|
return InTaintTime;
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
// higher level dependencies on the shape or body. Mostly used for LinkSets to
|
// higher level dependencies on the shape or body. Mostly used for LinkSets to
|
||||||
// remove the physical constraints before the body is destroyed.
|
// remove the physical constraints before the body is destroyed.
|
||||||
// Called at taint-time!!
|
// Called at taint-time!!
|
||||||
public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim,
|
public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim,
|
||||||
ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
|
ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
|
||||||
{
|
{
|
||||||
PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
|
PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
|
||||||
|
@ -126,7 +126,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim)
|
public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim)
|
||||||
{
|
{
|
||||||
return GetBodyAndShape(forceRebuild, sim, prim, null, null);
|
return GetBodyAndShape(forceRebuild, sim, prim, null, null);
|
||||||
}
|
}
|
||||||
|
@ -918,7 +918,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
// 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.
|
||||||
// Called at taint-time.
|
// Called at taint-time.
|
||||||
private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape,
|
private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BulletShape shape,
|
||||||
BodyDestructionCallback bodyCallback)
|
BodyDestructionCallback bodyCallback)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
|
@ -103,7 +103,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
|
||||||
Vector3 centerPos;
|
Vector3 centerPos;
|
||||||
centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f);
|
centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f);
|
||||||
centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f);
|
centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f);
|
||||||
centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f + 0.5f);
|
centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f - 0.5f);
|
||||||
|
|
||||||
m_mapInfo.terrainBody = new BulletBody(m_mapInfo.ID,
|
m_mapInfo.terrainBody = new BulletBody(m_mapInfo.ID,
|
||||||
BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr,
|
BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr,
|
||||||
|
|
|
@ -140,7 +140,7 @@ public sealed class BSTerrainManager : IDisposable
|
||||||
m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
|
m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
|
||||||
BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID,
|
BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID,
|
||||||
Vector3.Zero, Quaternion.Identity));
|
Vector3.Zero, Quaternion.Identity));
|
||||||
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr);
|
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr, Vector3.Zero, Quaternion.Identity);
|
||||||
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_groundPlane.ptr);
|
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_groundPlane.ptr);
|
||||||
// Ground plane does not move
|
// Ground plane does not move
|
||||||
BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
|
BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
|
||||||
|
@ -376,6 +376,7 @@ public sealed class BSTerrainManager : IDisposable
|
||||||
DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}",
|
DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}",
|
||||||
BSScene.DetailLogZero, pos, terrainBaseXYZ);
|
BSScene.DetailLogZero, pos, terrainBaseXYZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastHeight = ret;
|
lastHeight = ret;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,6 @@ public enum ConstraintType : int
|
||||||
MAX_CONSTRAINT_TYPE
|
MAX_CONSTRAINT_TYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ===============================================================================
|
// ===============================================================================
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct ConvexHull
|
public struct ConvexHull
|
||||||
|
|
|
@ -35,9 +35,9 @@ namespace OpenSim.Region.Physics.BulletSNPlugin
|
||||||
// These hold pointers to allocated objects in the unmanaged space.
|
// These hold pointers to allocated objects in the unmanaged space.
|
||||||
|
|
||||||
// The physics engine controller class created at initialization
|
// The physics engine controller class created at initialization
|
||||||
public struct BulletSim
|
public struct BulletWorld
|
||||||
{
|
{
|
||||||
public BulletSim(uint worldId, BSScene bss, object xx)
|
public BulletWorld(uint worldId, BSScene bss, object xx)
|
||||||
{
|
{
|
||||||
ptr = xx;
|
ptr = xx;
|
||||||
worldID = worldId;
|
worldID = worldId;
|
||||||
|
|
Loading…
Reference in New Issue