Merge branch 'master' of ssh://melanie@3dhosting.de/var/git/careminster into careminster
commit
5e3a76361f
|
@ -3956,6 +3956,34 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector3 GetGeometricCenter()
|
||||||
|
{
|
||||||
|
// this is not real geometric center but a average of positions relative to root prim acording to
|
||||||
|
// http://wiki.secondlife.com/wiki/llGetGeometricCenter
|
||||||
|
// ignoring tortured prims details since sl also seems to ignore
|
||||||
|
// so no real use in doing it on physics
|
||||||
|
|
||||||
|
Vector3 gc = Vector3.Zero;
|
||||||
|
|
||||||
|
int nparts = m_parts.Count;
|
||||||
|
if (nparts <= 1)
|
||||||
|
return gc;
|
||||||
|
|
||||||
|
SceneObjectPart[] parts = m_parts.GetArray();
|
||||||
|
nparts = parts.Length; // just in case it changed
|
||||||
|
if (nparts <= 1)
|
||||||
|
return gc;
|
||||||
|
|
||||||
|
// average all parts positions
|
||||||
|
for (int i = 0; i < nparts; i++)
|
||||||
|
gc += parts[i].GetWorldPosition();
|
||||||
|
gc /= nparts;
|
||||||
|
|
||||||
|
// relative to root:
|
||||||
|
gc -= AbsolutePosition;
|
||||||
|
return gc;
|
||||||
|
}
|
||||||
|
|
||||||
public float GetMass()
|
public float GetMass()
|
||||||
{
|
{
|
||||||
float retmass = 0f;
|
float retmass = 0f;
|
||||||
|
|
|
@ -123,6 +123,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </value>
|
/// </value>
|
||||||
public const int ALL_SIDES = -1;
|
public const int ALL_SIDES = -1;
|
||||||
|
|
||||||
|
private const scriptEvents PhyscicsNeededSubsEvents = (
|
||||||
|
scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end |
|
||||||
|
scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
|
||||||
|
);
|
||||||
|
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
/// <value>
|
/// <value>
|
||||||
|
@ -1821,18 +1826,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="rootObjectFlags"></param>
|
/// <param name="rootObjectFlags"></param>
|
||||||
/// <param name="VolumeDetectActive"></param>
|
/// <param name="VolumeDetectActive"></param>
|
||||||
|
/// <param name="building"></param>
|
||||||
|
|
||||||
public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive, bool building)
|
public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
|
||||||
{
|
{
|
||||||
|
VolumeDetectActive = _VolumeDetectActive; //?? as is used this is redundante
|
||||||
|
|
||||||
if (!ParentGroup.Scene.CollidablePrims)
|
if (!ParentGroup.Scene.CollidablePrims)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (PhysicsShapeType == (byte)PhysShapeType.none)
|
if (PhysicsShapeType == (byte)PhysShapeType.none)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0;
|
bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
|
||||||
bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0;
|
bool isPhantom = (_ObjectFlags & (uint) PrimFlags.Phantom) != 0;
|
||||||
|
|
||||||
|
|
||||||
if (IsJoint())
|
if (IsJoint())
|
||||||
{
|
{
|
||||||
|
@ -1840,68 +1847,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored
|
if ((!isPhantom || isPhysical || _VolumeDetectActive) && !ParentGroup.IsAttachment
|
||||||
// if (VolumeDetectActive)
|
&& !(Shape.PathCurve == (byte)Extrusion.Flexible))
|
||||||
// isPhantom = false;
|
AddToPhysics(isPhysical, isPhantom, building, true);
|
||||||
|
else
|
||||||
// The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition
|
PhysActor = null; // just to be sure
|
||||||
// or flexible
|
|
||||||
// if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
|
|
||||||
if ((!isPhantom || isPhysical || VolumeDetectActive) && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
|
|
||||||
{
|
|
||||||
Vector3 velocity = Velocity;
|
|
||||||
Vector3 rotationalVelocity = AngularVelocity;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape(
|
|
||||||
string.Format("{0}/{1}", Name, UUID),
|
|
||||||
Shape,
|
|
||||||
AbsolutePosition,
|
|
||||||
Scale,
|
|
||||||
GetWorldRotation(),
|
|
||||||
isPhysical,
|
|
||||||
isPhantom,
|
|
||||||
PhysicsShapeType,
|
|
||||||
m_localId);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid);
|
|
||||||
PhysActor = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhysicsActor pa = PhysActor;
|
|
||||||
|
|
||||||
if (pa != null)
|
|
||||||
{
|
|
||||||
pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
|
|
||||||
pa.SetMaterial(Material);
|
|
||||||
|
|
||||||
// if root part apply vehicle
|
|
||||||
if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
|
|
||||||
m_vehicle.SetVehicle(pa);
|
|
||||||
|
|
||||||
DoPhysicsPropertyUpdate(isPhysical, true);
|
|
||||||
if(VolumeDetectActive) // change if not the default only
|
|
||||||
pa.SetVolumeDetect(1);
|
|
||||||
|
|
||||||
if (!building)
|
|
||||||
pa.Building = false;
|
|
||||||
|
|
||||||
Velocity = velocity;
|
|
||||||
AngularVelocity = rotationalVelocity;
|
|
||||||
pa.Velocity = velocity;
|
|
||||||
pa.RotationalVelocity = rotationalVelocity;
|
|
||||||
|
|
||||||
// if not vehicle and root part apply force and torque
|
|
||||||
if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE)
|
|
||||||
&& LocalId == ParentGroup.RootPart.LocalId)
|
|
||||||
{
|
|
||||||
pa.Force = Force;
|
|
||||||
pa.Torque = Torque;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2310,18 +2260,29 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public Vector3 GetGeometricCenter()
|
public Vector3 GetGeometricCenter()
|
||||||
{
|
{
|
||||||
PhysicsActor pa = PhysActor;
|
// this is not real geometric center but a average of positions relative to root prim acording to
|
||||||
|
// http://wiki.secondlife.com/wiki/llGetGeometricCenter
|
||||||
if (pa != null)
|
// ignoring tortured prims details since sl also seems to ignore
|
||||||
{
|
// so no real use in doing it on physics
|
||||||
Vector3 vtmp = pa.CenterOfMass;
|
if (ParentGroup.IsDeleted)
|
||||||
return vtmp;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return new Vector3(0, 0, 0);
|
return new Vector3(0, 0, 0);
|
||||||
|
|
||||||
|
return ParentGroup.GetGeometricCenter();
|
||||||
|
|
||||||
|
/*
|
||||||
|
PhysicsActor pa = PhysActor;
|
||||||
|
|
||||||
|
if (pa != null)
|
||||||
|
{
|
||||||
|
Vector3 vtmp = pa.CenterOfMass;
|
||||||
|
return vtmp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return new Vector3(0, 0, 0);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public float GetMass()
|
public float GetMass()
|
||||||
{
|
{
|
||||||
PhysicsActor pa = PhysActor;
|
PhysicsActor pa = PhysActor;
|
||||||
|
|
||||||
|
@ -4628,7 +4589,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <param name="SetTemporary"></param>
|
/// <param name="SetTemporary"></param>
|
||||||
/// <param name="SetPhantom"></param>
|
/// <param name="SetPhantom"></param>
|
||||||
/// <param name="SetVD"></param>
|
/// <param name="SetVD"></param>
|
||||||
// public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD)
|
|
||||||
public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
|
public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
|
||||||
{
|
{
|
||||||
bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
|
bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
|
||||||
|
@ -4639,209 +4599,92 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
|
if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// do this first
|
|
||||||
if (building && PhysActor != null && PhysActor.Building != building)
|
|
||||||
PhysActor.Building = building;
|
|
||||||
|
|
||||||
// Special cases for VD. VD can only be called from a script
|
|
||||||
// and can't be combined with changes to other states. So we can rely
|
|
||||||
// that...
|
|
||||||
// ... if VD is changed, all others are not.
|
|
||||||
// ... if one of the others is changed, VD is not.
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (SetVD) // VD is active, special logic applies
|
|
||||||
|
|
||||||
volume detection is now independent of phantom in sl
|
|
||||||
|
|
||||||
{
|
|
||||||
// State machine logic for VolumeDetect
|
|
||||||
// More logic below
|
|
||||||
|
|
||||||
|
|
||||||
bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
|
|
||||||
|
|
||||||
if (phanReset) // Phantom changes from on to off switch VD off too
|
|
||||||
{
|
|
||||||
SetVD = false; // Switch it of for the course of this routine
|
|
||||||
VolumeDetectActive = false; // and also permanently
|
|
||||||
if (PhysActor != null)
|
|
||||||
PhysActor.SetVolumeDetect(0); // Let physics know about it too
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If volumedetect is active we don't want phantom to be applied.
|
|
||||||
// If this is a new call to VD out of the state "phantom"
|
|
||||||
// this will also cause the prim to be visible to physics
|
|
||||||
SetPhantom = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (wasVD)
|
|
||||||
{
|
|
||||||
// Correspondingly, if VD is turned off, also turn off phantom
|
|
||||||
SetPhantom = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UsePhysics && IsJoint())
|
|
||||||
{
|
|
||||||
SetPhantom = true;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if (UsePhysics)
|
if (UsePhysics)
|
||||||
{
|
|
||||||
AddFlag(PrimFlags.Physics);
|
AddFlag(PrimFlags.Physics);
|
||||||
/*
|
|
||||||
if (!wasUsingPhysics)
|
|
||||||
{
|
|
||||||
DoPhysicsPropertyUpdate(UsePhysics, false);
|
|
||||||
|
|
||||||
if (!ParentGroup.IsDeleted)
|
|
||||||
{
|
|
||||||
if (LocalId == ParentGroup.RootPart.LocalId)
|
|
||||||
{
|
|
||||||
ParentGroup.CheckSculptAndLoad();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
RemFlag(PrimFlags.Physics);
|
RemFlag(PrimFlags.Physics);
|
||||||
/*
|
|
||||||
if (wasUsingPhysics)
|
|
||||||
{
|
|
||||||
DoPhysicsPropertyUpdate(UsePhysics, false);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SetPhantom)
|
if (SetPhantom)
|
||||||
AddFlag(PrimFlags.Phantom);
|
AddFlag(PrimFlags.Phantom);
|
||||||
else
|
else
|
||||||
RemFlag(PrimFlags.Phantom);
|
RemFlag(PrimFlags.Phantom);
|
||||||
|
|
||||||
|
if (SetTemporary)
|
||||||
|
AddFlag(PrimFlags.TemporaryOnRez);
|
||||||
|
else
|
||||||
|
RemFlag(PrimFlags.TemporaryOnRez);
|
||||||
|
|
||||||
|
VolumeDetectActive = SetVD;
|
||||||
|
|
||||||
|
if (ParentGroup.Scene == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PhysicsActor pa = PhysActor;
|
||||||
|
|
||||||
|
if (pa != null && building && pa.Building != building)
|
||||||
|
pa.Building = building;
|
||||||
|
|
||||||
if ((SetPhantom && !UsePhysics) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
|
if ((SetPhantom && !UsePhysics) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
|
||||||
|| (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
|
|| (Shape.PathCurve == (byte)Extrusion.Flexible))
|
||||||
{
|
{
|
||||||
// AddFlag(PrimFlags.Phantom);
|
if (pa != null)
|
||||||
|
{
|
||||||
|
ParentGroup.Scene.RemovePhysicalPrim(1);
|
||||||
|
RemoveFromPhysics();
|
||||||
|
}
|
||||||
|
|
||||||
Velocity = new Vector3(0, 0, 0);
|
Velocity = new Vector3(0, 0, 0);
|
||||||
Acceleration = new Vector3(0, 0, 0);
|
Acceleration = new Vector3(0, 0, 0);
|
||||||
if (ParentGroup.RootPart == this)
|
if (ParentGroup.RootPart == this)
|
||||||
AngularVelocity = new Vector3(0, 0, 0);
|
AngularVelocity = new Vector3(0, 0, 0);
|
||||||
|
|
||||||
if (PhysActor != null)
|
|
||||||
{
|
|
||||||
ParentGroup.Scene.RemovePhysicalPrim(1);
|
|
||||||
RemoveFromPhysics();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ParentGroup.Scene == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (ParentGroup.Scene.CollidablePrims)
|
if (ParentGroup.Scene.CollidablePrims)
|
||||||
{
|
{
|
||||||
if (PhysActor == null)
|
if (pa == null)
|
||||||
{
|
{
|
||||||
PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape(
|
AddToPhysics(UsePhysics, SetPhantom, building , false);
|
||||||
string.Format("{0}/{1}", Name, UUID),
|
pa = PhysActor;
|
||||||
Shape,
|
|
||||||
AbsolutePosition,
|
|
||||||
Scale,
|
|
||||||
GetWorldRotation(), //physics wants world rotation like all other functions send
|
|
||||||
UsePhysics,
|
|
||||||
SetPhantom,
|
|
||||||
PhysicsShapeType,
|
|
||||||
m_localId);
|
|
||||||
|
|
||||||
PhysActor.SetMaterial(Material);
|
if (pa != null)
|
||||||
|
|
||||||
// if root part apply vehicle
|
|
||||||
if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
|
|
||||||
m_vehicle.SetVehicle(PhysActor);
|
|
||||||
|
|
||||||
DoPhysicsPropertyUpdate(UsePhysics, true);
|
|
||||||
|
|
||||||
if (!ParentGroup.IsDeleted)
|
|
||||||
{
|
{
|
||||||
if (LocalId == ParentGroup.RootPart.LocalId)
|
if (
|
||||||
|
// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
|
||||||
|
// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
|
||||||
|
// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
|
||||||
|
// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
|
||||||
|
// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
|
||||||
|
// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
|
||||||
|
((AggregateScriptEvents & PhyscicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
|
||||||
|
// (CollisionSound != UUID.Zero)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
ParentGroup.CheckSculptAndLoad();
|
pa.OnCollisionUpdate += PhysicsCollision;
|
||||||
|
pa.SubscribeEvents(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
|
||||||
((AggregateScriptEvents & scriptEvents.collision) != 0) ||
|
|
||||||
((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
|
|
||||||
((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
|
|
||||||
((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
|
|
||||||
((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
|
|
||||||
((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
|
|
||||||
(CollisionSound != UUID.Zero)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PhysActor.OnCollisionUpdate += PhysicsCollision;
|
|
||||||
PhysActor.SubscribeEvents(1000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else // it already has a physical representation
|
else // it already has a physical representation
|
||||||
{
|
{
|
||||||
DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
|
DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
|
||||||
|
|
||||||
if (!ParentGroup.IsDeleted)
|
if(VolumeDetectActive)
|
||||||
{
|
pa.SetVolumeDetect(1);
|
||||||
if (LocalId == ParentGroup.RootPart.LocalId)
|
else
|
||||||
{
|
pa.SetVolumeDetect(0);
|
||||||
ParentGroup.CheckSculptAndLoad();
|
|
||||||
}
|
if (pa.Building != building)
|
||||||
}
|
pa.Building = building;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsActor pa = PhysActor;
|
|
||||||
if (SetVD)
|
|
||||||
{
|
|
||||||
// If the above logic worked (this is urgent candidate to unit tests!)
|
|
||||||
// we now have a physicsactor.
|
|
||||||
// Defensive programming calls for a check here.
|
|
||||||
// Better would be throwing an exception that could be catched by a unit test as the internal
|
|
||||||
// logic should make sure, this Physactor is always here.
|
|
||||||
if (pa != null)
|
|
||||||
{
|
|
||||||
pa.SetVolumeDetect(1);
|
|
||||||
// AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active
|
|
||||||
this.VolumeDetectActive = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like
|
|
||||||
// (mumbles, well, at least if you have infinte CPU powers :-))
|
|
||||||
if (pa != null)
|
|
||||||
{
|
|
||||||
pa.SetVolumeDetect(0);
|
|
||||||
this.VolumeDetectActive = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SetTemporary)
|
|
||||||
{
|
|
||||||
AddFlag(PrimFlags.TemporaryOnRez);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RemFlag(PrimFlags.TemporaryOnRez);
|
|
||||||
}
|
|
||||||
|
|
||||||
// m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
|
// m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
|
||||||
|
|
||||||
// and last in case we have a new actor and not building
|
// and last in case we have a new actor and not building
|
||||||
if (pa != null && pa.Building != building)
|
|
||||||
pa.Building = building;
|
|
||||||
if (ParentGroup != null)
|
if (ParentGroup != null)
|
||||||
{
|
{
|
||||||
ParentGroup.HasGroupChanged = true;
|
ParentGroup.HasGroupChanged = true;
|
||||||
|
@ -4853,48 +4696,104 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds this part to the physics scene.
|
/// Adds this part to the physics scene.
|
||||||
|
/// and sets the PhysActor property
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>This method also sets the PhysActor property.</remarks>
|
/// <param name="isPhysical">Add this prim as physical.</param>
|
||||||
/// <param name="rigidBody">Add this prim with a rigid body.</param>
|
/// <param name="isPhantom">Add this prim as phantom.</param>
|
||||||
/// <returns>
|
/// <param name="building">tells physics to delay full construction of object</param>
|
||||||
/// The physics actor. null if there was a failure.
|
/// <param name="applyDynamics">applies velocities, force and torque</param>
|
||||||
/// </returns>
|
private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
|
||||||
private PhysicsActor AddToPhysics(bool rigidBody)
|
|
||||||
{
|
{
|
||||||
PhysicsActor pa;
|
PhysicsActor pa;
|
||||||
|
|
||||||
|
Vector3 velocity = Velocity;
|
||||||
|
Vector3 rotationalVelocity = AngularVelocity;;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
|
pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
|
||||||
string.Format("{0}/{1}", Name, UUID),
|
string.Format("{0}/{1}", Name, UUID),
|
||||||
Shape,
|
Shape,
|
||||||
AbsolutePosition,
|
AbsolutePosition,
|
||||||
Scale,
|
Scale,
|
||||||
RotationOffset,
|
GetWorldRotation(),
|
||||||
rigidBody,
|
isPhysical,
|
||||||
m_localId);
|
isPhantom,
|
||||||
|
PhysicsShapeType,
|
||||||
|
m_localId);
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid);
|
m_log.ErrorFormat("[SCENE]: AddToPhysics object {0} failed: {1}", m_uuid, ex.Message);
|
||||||
pa = null;
|
pa = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical
|
|
||||||
// properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor
|
|
||||||
// being set.
|
|
||||||
PhysActor = pa;
|
|
||||||
|
|
||||||
// Basic Physics can also return null as well as an exception catch.
|
|
||||||
if (pa != null)
|
if (pa != null)
|
||||||
{
|
{
|
||||||
pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
|
pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
|
||||||
pa.SetMaterial(Material);
|
pa.SetMaterial(Material);
|
||||||
DoPhysicsPropertyUpdate(rigidBody, true);
|
|
||||||
|
if (VolumeDetectActive) // change if not the default only
|
||||||
|
pa.SetVolumeDetect(1);
|
||||||
|
|
||||||
|
if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
|
||||||
|
m_vehicle.SetVehicle(pa);
|
||||||
|
|
||||||
|
// we are going to tell rest of code about physics so better have this here
|
||||||
|
PhysActor = pa;
|
||||||
|
|
||||||
|
// DoPhysicsPropertyUpdate(isPhysical, true);
|
||||||
|
// lets expand it here just with what it really needs to do
|
||||||
|
|
||||||
|
if (isPhysical)
|
||||||
|
{
|
||||||
|
if (ParentGroup.RootPart.KeyframeMotion != null)
|
||||||
|
ParentGroup.RootPart.KeyframeMotion.Stop();
|
||||||
|
ParentGroup.RootPart.KeyframeMotion = null;
|
||||||
|
ParentGroup.Scene.AddPhysicalPrim(1);
|
||||||
|
|
||||||
|
pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
|
||||||
|
pa.OnOutOfBounds += PhysicsOutOfBounds;
|
||||||
|
|
||||||
|
if (ParentID != 0 && ParentID != LocalId)
|
||||||
|
{
|
||||||
|
PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
|
||||||
|
|
||||||
|
if (parentPa != null)
|
||||||
|
{
|
||||||
|
pa.link(parentPa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (applyDynamics)
|
||||||
|
// do independent of isphysical so parameters get setted (at least some)
|
||||||
|
{
|
||||||
|
Velocity = velocity;
|
||||||
|
AngularVelocity = rotationalVelocity;
|
||||||
|
pa.Velocity = velocity;
|
||||||
|
pa.RotationalVelocity = rotationalVelocity;
|
||||||
|
|
||||||
|
// if not vehicle and root part apply force and torque
|
||||||
|
if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE)
|
||||||
|
&& LocalId == ParentGroup.RootPart.LocalId)
|
||||||
|
{
|
||||||
|
pa.Force = Force;
|
||||||
|
pa.Torque = Torque;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Shape.SculptEntry)
|
||||||
|
CheckSculptAndLoad();
|
||||||
|
else
|
||||||
|
ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
|
||||||
|
|
||||||
|
if (!building)
|
||||||
|
pa.Building = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pa;
|
PhysActor = pa;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This removes the part from the physics scene.
|
/// This removes the part from the physics scene.
|
||||||
|
@ -5103,10 +5002,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
PhysicsActor pa = PhysActor;
|
PhysicsActor pa = PhysActor;
|
||||||
if (pa != null)
|
if (pa != null)
|
||||||
{
|
{
|
||||||
const scriptEvents NeededSubsEvents = (
|
|
||||||
scriptEvents.collision | scriptEvents.collision_start| scriptEvents.collision_end |
|
|
||||||
scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
|
|
||||||
);
|
|
||||||
if (
|
if (
|
||||||
// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
|
// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
|
||||||
// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
|
// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
|
||||||
|
@ -5114,7 +5009,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
|
// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
|
||||||
// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
|
// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
|
||||||
// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
|
// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
|
||||||
((AggregateScriptEvents & NeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
|
((AggregateScriptEvents & PhyscicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// subscribe to physics updates.
|
// subscribe to physics updates.
|
||||||
|
|
|
@ -179,6 +179,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
public bool m_outofBounds;
|
public bool m_outofBounds;
|
||||||
private float m_density = 10.000006836f; // Aluminum g/cm3;
|
private float m_density = 10.000006836f; // Aluminum g/cm3;
|
||||||
|
|
||||||
|
private float m_primMass = 10.000006836f; // Aluminum g/cm3;
|
||||||
|
|
||||||
private byte m_shapetype;
|
private byte m_shapetype;
|
||||||
private byte m_taintshapetype;
|
private byte m_taintshapetype;
|
||||||
|
|
||||||
|
@ -538,7 +540,11 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
public override float Mass
|
public override float Mass
|
||||||
{
|
{
|
||||||
get { return CalculateMass(); }
|
get
|
||||||
|
{
|
||||||
|
CalculateMass();
|
||||||
|
return m_primMass;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Vector3 Force
|
public override Vector3 Force
|
||||||
|
@ -1316,6 +1322,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
m_primMass = returnMass;
|
||||||
|
if (m_primMass > _parent_scene.maximumMassObject)
|
||||||
|
m_primMass = _parent_scene.maximumMassObject;
|
||||||
|
|
||||||
// Recursively calculate mass
|
// Recursively calculate mass
|
||||||
bool HasChildPrim = false;
|
bool HasChildPrim = false;
|
||||||
|
|
|
@ -395,7 +395,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
public override float Mass
|
public override float Mass
|
||||||
{
|
{
|
||||||
get { return _mass; }
|
get { return primMass; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Vector3 Force
|
public override Vector3 Force
|
||||||
|
|
|
@ -107,16 +107,17 @@ namespace OdeAPI
|
||||||
ConvexClass,
|
ConvexClass,
|
||||||
GeomTransformClass,
|
GeomTransformClass,
|
||||||
TriMeshClass,
|
TriMeshClass,
|
||||||
HeightfieldClass,
|
HeightfieldClass,
|
||||||
FirstSpaceClass,
|
FirstSpaceClass,
|
||||||
SimpleSpaceClass = FirstSpaceClass,
|
SimpleSpaceClass = FirstSpaceClass,
|
||||||
HashSpaceClass,
|
HashSpaceClass,
|
||||||
QuadTreeSpaceClass,
|
QuadTreeSpaceClass,
|
||||||
LastSpaceClass = QuadTreeSpaceClass,
|
LastSpaceClass = QuadTreeSpaceClass,
|
||||||
|
UbitTerrainClass,
|
||||||
FirstUserClass,
|
FirstUserClass,
|
||||||
LastUserClass = FirstUserClass + MaxUserClasses - 1,
|
LastUserClass = FirstUserClass + MaxUserClasses - 1,
|
||||||
NumClasses,
|
NumClasses,
|
||||||
MaxUserClasses = 4
|
MaxUserClasses = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum JointType : int
|
public enum JointType : int
|
||||||
|
@ -201,8 +202,11 @@ namespace OdeAPI
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void GeomDtorFn(IntPtr o);
|
public delegate void GeomDtorFn(IntPtr o);
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate dReal HeightfieldGetHeight(IntPtr p_user_data, int x, int z);
|
public delegate dReal HeightfieldGetHeight(IntPtr p_user_data, int x, int z);
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
public delegate dReal UbitTerrainGetHeight(IntPtr p_user_data, int x, int z);
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void NearCallback(IntPtr data, IntPtr geom1, IntPtr geom2);
|
public delegate void NearCallback(IntPtr data, IntPtr geom1, IntPtr geom2);
|
||||||
|
@ -729,6 +733,18 @@ namespace OdeAPI
|
||||||
return CreateiHeightfield(space, data, bPlaceable);
|
return CreateiHeightfield(space, data, bPlaceable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateUbitTerrain"), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern IntPtr CreateiUbitTerrain(IntPtr space, IntPtr data, int bPlaceable);
|
||||||
|
public static IntPtr CreateUbitTerrain(IntPtr space, IntPtr data, int bPlaceable)
|
||||||
|
{
|
||||||
|
NTotalGeoms++;
|
||||||
|
return CreateiUbitTerrain(space, data, bPlaceable);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeom"), SuppressUnmanagedCodeSecurity]
|
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeom"), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern IntPtr CreateiGeom(int classnum);
|
public static extern IntPtr CreateiGeom(int classnum);
|
||||||
public static IntPtr CreateGeom(int classnum)
|
public static IntPtr CreateGeom(int classnum)
|
||||||
|
@ -964,6 +980,8 @@ namespace OdeAPI
|
||||||
dReal width, dReal depth, int widthSamples, int depthSamples,
|
dReal width, dReal depth, int widthSamples, int depthSamples,
|
||||||
dReal scale, dReal offset, dReal thickness, int bWrap);
|
dReal scale, dReal offset, dReal thickness, int bWrap);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity]
|
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, double[] pHeightData, int bCopyHeightData,
|
public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, double[] pHeightData, int bCopyHeightData,
|
||||||
dReal width, dReal depth, int widthSamples, int depthSamples,
|
dReal width, dReal depth, int widthSamples, int depthSamples,
|
||||||
|
@ -989,6 +1007,33 @@ namespace OdeAPI
|
||||||
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldSetHeightfieldData"), SuppressUnmanagedCodeSecurity]
|
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldSetHeightfieldData"), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void GeomHeightfieldSetHeightfieldData(IntPtr g, IntPtr d);
|
public static extern void GeomHeightfieldSetHeightfieldData(IntPtr g, IntPtr d);
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainDataBuild"), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void GeomUbitTerrainDataBuild(IntPtr d, float[] pHeightData, int bCopyHeightData,
|
||||||
|
dReal sampleSize, int widthSamples, int depthSamples,
|
||||||
|
dReal offset, dReal thickness, int bWrap);
|
||||||
|
|
||||||
|
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainDataBuild"), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void GeomUbitTerrainDataBuild(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
|
||||||
|
dReal sampleSize, int widthSamples, int depthSamples,
|
||||||
|
dReal thickness, int bWrap);
|
||||||
|
|
||||||
|
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainDataCreate"), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern IntPtr GeomUbitTerrainDataCreate();
|
||||||
|
|
||||||
|
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainDataDestroy"), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void GeomUbitTerrainDataDestroy(IntPtr d);
|
||||||
|
|
||||||
|
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainDataSetBounds"), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void GeomUbitTerrainDataSetBounds(IntPtr d, dReal minHeight, dReal maxHeight);
|
||||||
|
|
||||||
|
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainGetHeightfieldData"), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern IntPtr GeomUbitTerrainGetHeightfieldData(IntPtr g);
|
||||||
|
|
||||||
|
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainSetHeightfieldData"), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void GeomUbitTerrainSetHeightfieldData(IntPtr g, IntPtr d);
|
||||||
|
|
||||||
|
|
||||||
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsEnabled"), SuppressUnmanagedCodeSecurity]
|
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsEnabled"), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern bool GeomIsEnabled(IntPtr geom);
|
public static extern bool GeomIsEnabled(IntPtr geom);
|
||||||
|
|
||||||
|
|
|
@ -156,6 +156,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
private readonly ILog m_log;
|
private readonly ILog m_log;
|
||||||
// private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>();
|
// private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>();
|
||||||
|
|
||||||
|
public bool OdeUbitLib = false;
|
||||||
// private int threadid = 0;
|
// private int threadid = 0;
|
||||||
private Random fluidRandomizer = new Random(Environment.TickCount);
|
private Random fluidRandomizer = new Random(Environment.TickCount);
|
||||||
|
|
||||||
|
@ -374,7 +375,14 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
mesher = meshmerizer;
|
mesher = meshmerizer;
|
||||||
m_config = config;
|
m_config = config;
|
||||||
|
|
||||||
// m_log.WarnFormat("ODE configuration: {0}", d.GetConfiguration("ODE"));
|
string ode_config = d.GetConfiguration("ODE");
|
||||||
|
m_log.WarnFormat("ODE configuration: {0}", ode_config);
|
||||||
|
|
||||||
|
if (ode_config.Contains("ODE_Ubit"))
|
||||||
|
{
|
||||||
|
OdeUbitLib = true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (region != null)
|
if (region != null)
|
||||||
{
|
{
|
||||||
|
@ -527,13 +535,24 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
// sets a global contact for a joint for contactgeom , and base contact description)
|
// sets a global contact for a joint for contactgeom , and base contact description)
|
||||||
|
|
||||||
private IntPtr CreateContacJoint(ref d.ContactGeom contactGeom, float mu, float bounce,float cfm,float erp)
|
private IntPtr CreateContacJoint(ref d.ContactGeom contactGeom, float mu, float bounce, float cfm, float erpscale, float dscale)
|
||||||
{
|
{
|
||||||
if (GlobalContactsArray == IntPtr.Zero || m_global_contactcount >= maxContactsbeforedeath)
|
if (GlobalContactsArray == IntPtr.Zero || m_global_contactcount >= maxContactsbeforedeath)
|
||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
|
|
||||||
|
float erp = contactGeom.depth;
|
||||||
|
erp *= erpscale;
|
||||||
|
if (erp < minERP)
|
||||||
|
erp = minERP;
|
||||||
|
else if (erp > MaxERP)
|
||||||
|
erp = MaxERP;
|
||||||
|
|
||||||
|
float depth = contactGeom.depth * dscale;
|
||||||
|
if (depth > 0.5f)
|
||||||
|
depth = 0.5f;
|
||||||
|
|
||||||
d.Contact newcontact = new d.Contact();
|
d.Contact newcontact = new d.Contact();
|
||||||
newcontact.geom.depth = contactGeom.depth;
|
newcontact.geom.depth = depth;
|
||||||
newcontact.geom.g1 = contactGeom.g1;
|
newcontact.geom.g1 = contactGeom.g1;
|
||||||
newcontact.geom.g2 = contactGeom.g2;
|
newcontact.geom.g2 = contactGeom.g2;
|
||||||
newcontact.geom.pos = contactGeom.pos;
|
newcontact.geom.pos = contactGeom.pos;
|
||||||
|
@ -692,6 +711,10 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
float bounce = 0;
|
float bounce = 0;
|
||||||
float cfm = 0.0001f;
|
float cfm = 0.0001f;
|
||||||
float erp = 0.1f;
|
float erp = 0.1f;
|
||||||
|
float erpscale = 1.0f;
|
||||||
|
float dscale = 1.0f;
|
||||||
|
bool IgnoreNegSides = false;
|
||||||
|
|
||||||
|
|
||||||
ContactData contactdata1 = new ContactData(0, 0, false);
|
ContactData contactdata1 = new ContactData(0, 0, false);
|
||||||
ContactData contactdata2 = new ContactData(0, 0, false);
|
ContactData contactdata2 = new ContactData(0, 0, false);
|
||||||
|
@ -781,10 +804,14 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
cfm = p1.Mass;
|
cfm = p1.Mass;
|
||||||
if (cfm > p2.Mass)
|
if (cfm > p2.Mass)
|
||||||
cfm = p2.Mass;
|
cfm = p2.Mass;
|
||||||
cfm = (float)Math.Sqrt(cfm);
|
dscale = 10 / cfm;
|
||||||
cfm *= 0.0001f;
|
dscale = (float)Math.Sqrt(dscale);
|
||||||
if (cfm > 0.8f)
|
if (dscale > 1.0f)
|
||||||
cfm = 0.8f;
|
dscale = 1.0f;
|
||||||
|
erpscale = cfm * 0.01f;
|
||||||
|
cfm = 0.0001f / cfm;
|
||||||
|
if (cfm > 0.01f)
|
||||||
|
cfm = 0.01f;
|
||||||
|
|
||||||
if ((Math.Abs(p2.Velocity.X - p1.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y - p1.Velocity.Y) > 0.1f))
|
if ((Math.Abs(p2.Velocity.X - p1.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y - p1.Velocity.Y) > 0.1f))
|
||||||
mu *= frictionMovementMult;
|
mu *= frictionMovementMult;
|
||||||
|
@ -801,11 +828,22 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
if (Math.Abs(p1.Velocity.X) > 0.1f || Math.Abs(p1.Velocity.Y) > 0.1f)
|
if (Math.Abs(p1.Velocity.X) > 0.1f || Math.Abs(p1.Velocity.Y) > 0.1f)
|
||||||
mu *= frictionMovementMult;
|
mu *= frictionMovementMult;
|
||||||
p1.CollidingGround = true;
|
p1.CollidingGround = true;
|
||||||
|
|
||||||
cfm = p1.Mass;
|
cfm = p1.Mass;
|
||||||
cfm = (float)Math.Sqrt(cfm);
|
dscale = 10 / cfm;
|
||||||
cfm *= 0.0001f;
|
dscale = (float)Math.Sqrt(dscale);
|
||||||
if (cfm > 0.8f)
|
if (dscale > 1.0f)
|
||||||
cfm = 0.8f;
|
dscale = 1.0f;
|
||||||
|
erpscale = cfm * 0.01f;
|
||||||
|
cfm = 0.0001f / cfm;
|
||||||
|
if (cfm > 0.01f)
|
||||||
|
cfm = 0.01f;
|
||||||
|
|
||||||
|
if (d.GeomGetClass(g1) == d.GeomClassID.TriMeshClass)
|
||||||
|
{
|
||||||
|
if (curContact.side1 > 0)
|
||||||
|
IgnoreNegSides = true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (name == "Water")
|
else if (name == "Water")
|
||||||
|
@ -830,11 +868,21 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
p2.getContactData(ref contactdata2);
|
p2.getContactData(ref contactdata2);
|
||||||
bounce = contactdata2.bounce * TerrainBounce;
|
bounce = contactdata2.bounce * TerrainBounce;
|
||||||
mu = (float)Math.Sqrt(contactdata2.mu * TerrainFriction);
|
mu = (float)Math.Sqrt(contactdata2.mu * TerrainFriction);
|
||||||
|
|
||||||
cfm = p2.Mass;
|
cfm = p2.Mass;
|
||||||
cfm = (float)Math.Sqrt(cfm);
|
dscale = 10 / cfm;
|
||||||
cfm *= 0.0001f;
|
dscale = (float)Math.Sqrt(dscale);
|
||||||
if (cfm > 0.8f)
|
|
||||||
cfm = 0.8f;
|
if (dscale > 1.0f)
|
||||||
|
dscale = 1.0f;
|
||||||
|
|
||||||
|
erpscale = cfm * 0.01f;
|
||||||
|
cfm = 0.0001f / cfm;
|
||||||
|
if (cfm > 0.01f)
|
||||||
|
cfm = 0.01f;
|
||||||
|
|
||||||
|
if (curContact.side1 > 0) // should be 2 ?
|
||||||
|
IgnoreNegSides = true;
|
||||||
|
|
||||||
if (Math.Abs(p2.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y) > 0.1f)
|
if (Math.Abs(p2.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y) > 0.1f)
|
||||||
mu *= frictionMovementMult;
|
mu *= frictionMovementMult;
|
||||||
|
@ -862,39 +910,45 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
if (dop1foot && (p1.Position.Z - curContact.pos.Z) > (p1.Size.Z - avCapRadius) * 0.5f)
|
|
||||||
p1.IsColliding = true;
|
|
||||||
if (dop2foot && (p2.Position.Z - curContact.pos.Z) > (p2.Size.Z - avCapRadius) * 0.5f)
|
|
||||||
p2.IsColliding = true;
|
|
||||||
|
|
||||||
|
if (IgnoreNegSides && curContact.side1 < 0)
|
||||||
erp = curContact.depth;
|
|
||||||
if (erp < minERP)
|
|
||||||
erp = minERP;
|
|
||||||
else if (erp > MaxERP)
|
|
||||||
erp = MaxERP;
|
|
||||||
|
|
||||||
Joint = CreateContacJoint(ref curContact, mu, bounce,cfm,erp);
|
|
||||||
d.JointAttach(Joint, b1, b2);
|
|
||||||
|
|
||||||
if (++m_global_contactcount >= maxContactsbeforedeath)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if(++i >= count)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!GetCurContactGeom(i, ref curContact))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (curContact.depth > maxDepthContact.PenetrationDepth)
|
|
||||||
{
|
{
|
||||||
maxDepthContact.Position.X = curContact.pos.X;
|
if (++i >= count)
|
||||||
maxDepthContact.Position.Y = curContact.pos.Y;
|
break;
|
||||||
maxDepthContact.Position.Z = curContact.pos.Z;
|
|
||||||
maxDepthContact.SurfaceNormal.X = curContact.normal.X;
|
if (!GetCurContactGeom(i, ref curContact))
|
||||||
maxDepthContact.SurfaceNormal.Y = curContact.normal.Y;
|
break;
|
||||||
maxDepthContact.SurfaceNormal.Z = curContact.normal.Z;
|
}
|
||||||
maxDepthContact.PenetrationDepth = curContact.depth;
|
else
|
||||||
|
|
||||||
|
{
|
||||||
|
if (dop1foot && (p1.Position.Z - curContact.pos.Z) > (p1.Size.Z - avCapRadius) * 0.5f)
|
||||||
|
p1.IsColliding = true;
|
||||||
|
if (dop2foot && (p2.Position.Z - curContact.pos.Z) > (p2.Size.Z - avCapRadius) * 0.5f)
|
||||||
|
p2.IsColliding = true;
|
||||||
|
|
||||||
|
Joint = CreateContacJoint(ref curContact, mu, bounce, cfm, erpscale, dscale);
|
||||||
|
d.JointAttach(Joint, b1, b2);
|
||||||
|
|
||||||
|
if (++m_global_contactcount >= maxContactsbeforedeath)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (++i >= count)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!GetCurContactGeom(i, ref curContact))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (curContact.depth > maxDepthContact.PenetrationDepth)
|
||||||
|
{
|
||||||
|
maxDepthContact.Position.X = curContact.pos.X;
|
||||||
|
maxDepthContact.Position.Y = curContact.pos.Y;
|
||||||
|
maxDepthContact.Position.Z = curContact.pos.Z;
|
||||||
|
maxDepthContact.SurfaceNormal.X = curContact.normal.X;
|
||||||
|
maxDepthContact.SurfaceNormal.Y = curContact.normal.Y;
|
||||||
|
maxDepthContact.SurfaceNormal.Z = curContact.normal.Z;
|
||||||
|
maxDepthContact.PenetrationDepth = curContact.depth;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1865,13 +1919,12 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
public float GetTerrainHeightAtXY(float x, float y)
|
public float GetTerrainHeightAtXY(float x, float y)
|
||||||
{
|
{
|
||||||
// assumes 1m size grid and constante size square regions
|
|
||||||
// needs to know about sims around in future
|
|
||||||
// region offset in mega position
|
|
||||||
|
|
||||||
int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
|
int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
|
||||||
int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
|
int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
|
||||||
|
|
||||||
|
|
||||||
IntPtr heightFieldGeom = IntPtr.Zero;
|
IntPtr heightFieldGeom = IntPtr.Zero;
|
||||||
|
|
||||||
// get region map
|
// get region map
|
||||||
|
@ -1903,28 +1956,55 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
int regsize = (int)Constants.RegionSize + 3; // map size see setterrain number of samples
|
int regsize = (int)Constants.RegionSize + 3; // map size see setterrain number of samples
|
||||||
|
|
||||||
// we still have square fixed size regions
|
if (OdeUbitLib)
|
||||||
// also flip x and y because of how map is done for ODE fliped axis
|
|
||||||
// so ix,iy,dx and dy are inter exchanged
|
|
||||||
if (x < regsize - 1)
|
|
||||||
{
|
{
|
||||||
iy = (int)x;
|
if (x < regsize - 1)
|
||||||
dy = x - (float)iy;
|
{
|
||||||
}
|
ix = (int)x;
|
||||||
else // out world use external height
|
dx = x - (float)ix;
|
||||||
{
|
}
|
||||||
iy = regsize - 1;
|
else // out world use external height
|
||||||
dy = 0;
|
{
|
||||||
}
|
ix = regsize - 1;
|
||||||
if (y < regsize - 1)
|
dx = 0;
|
||||||
{
|
}
|
||||||
ix = (int)y;
|
if (y < regsize - 1)
|
||||||
dx = y - (float)ix;
|
{
|
||||||
|
iy = (int)y;
|
||||||
|
dy = y - (float)iy;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iy = regsize - 1;
|
||||||
|
dy = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ix = regsize - 1;
|
// we still have square fixed size regions
|
||||||
dx = 0;
|
// also flip x and y because of how map is done for ODE fliped axis
|
||||||
|
// so ix,iy,dx and dy are inter exchanged
|
||||||
|
if (x < regsize - 1)
|
||||||
|
{
|
||||||
|
iy = (int)x;
|
||||||
|
dy = x - (float)iy;
|
||||||
|
}
|
||||||
|
else // out world use external height
|
||||||
|
{
|
||||||
|
iy = regsize - 1;
|
||||||
|
dy = 0;
|
||||||
|
}
|
||||||
|
if (y < regsize - 1)
|
||||||
|
{
|
||||||
|
ix = (int)y;
|
||||||
|
dx = y - (float)ix;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ix = regsize - 1;
|
||||||
|
dx = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float h0;
|
float h0;
|
||||||
|
@ -1951,6 +2031,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
return h0 + h1 + h2;
|
return h0 + h1 + h2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override void SetTerrain(float[] heightMap)
|
public override void SetTerrain(float[] heightMap)
|
||||||
{
|
{
|
||||||
if (m_worldOffset != Vector3.Zero && m_parentScene != null)
|
if (m_worldOffset != Vector3.Zero && m_parentScene != null)
|
||||||
|
@ -1972,7 +2054,15 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTerrain(float[] heightMap, Vector3 pOffset)
|
public void SetTerrain(float[] heightMap, Vector3 pOffset)
|
||||||
{
|
{
|
||||||
|
if (OdeUbitLib)
|
||||||
|
UbitSetTerrain(heightMap, pOffset);
|
||||||
|
else
|
||||||
|
OriSetTerrain(heightMap, pOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OriSetTerrain(float[] heightMap, Vector3 pOffset)
|
||||||
|
{
|
||||||
// assumes 1m size grid and constante size square regions
|
// assumes 1m size grid and constante size square regions
|
||||||
// needs to know about sims around in future
|
// needs to know about sims around in future
|
||||||
|
|
||||||
|
@ -2086,6 +2176,108 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UbitSetTerrain(float[] heightMap, Vector3 pOffset)
|
||||||
|
{
|
||||||
|
// assumes 1m size grid and constante size square regions
|
||||||
|
// needs to know about sims around in future
|
||||||
|
|
||||||
|
float[] _heightmap;
|
||||||
|
|
||||||
|
uint heightmapWidth = Constants.RegionSize + 2;
|
||||||
|
uint heightmapHeight = Constants.RegionSize + 2;
|
||||||
|
|
||||||
|
uint heightmapWidthSamples = heightmapWidth + 1;
|
||||||
|
uint heightmapHeightSamples = heightmapHeight + 1;
|
||||||
|
|
||||||
|
_heightmap = new float[heightmapWidthSamples * heightmapHeightSamples];
|
||||||
|
|
||||||
|
|
||||||
|
uint regionsize = Constants.RegionSize;
|
||||||
|
|
||||||
|
float hfmin = float.MaxValue;
|
||||||
|
// float hfmax = float.MinValue;
|
||||||
|
float val;
|
||||||
|
|
||||||
|
|
||||||
|
uint maxXXYY = regionsize - 1;
|
||||||
|
// adding one margin all around so things don't fall in edges
|
||||||
|
|
||||||
|
uint xx;
|
||||||
|
uint yy = 0;
|
||||||
|
uint yt = 0;
|
||||||
|
|
||||||
|
for (uint y = 0; y < heightmapHeightSamples; y++)
|
||||||
|
{
|
||||||
|
if (y > 1 && y < maxXXYY)
|
||||||
|
yy += regionsize;
|
||||||
|
xx = 0;
|
||||||
|
for (uint x = 0; x < heightmapWidthSamples; x++)
|
||||||
|
{
|
||||||
|
if (x > 1 && x < maxXXYY)
|
||||||
|
xx++;
|
||||||
|
|
||||||
|
val = heightMap[yy + xx];
|
||||||
|
if (val < 0.0f)
|
||||||
|
val = 0.0f; // no neg terrain as in chode
|
||||||
|
_heightmap[yt + x] = val;
|
||||||
|
|
||||||
|
if (hfmin > val)
|
||||||
|
hfmin = val;
|
||||||
|
// if (hfmax < val)
|
||||||
|
// hfmax = val;
|
||||||
|
}
|
||||||
|
yt += heightmapWidthSamples;
|
||||||
|
}
|
||||||
|
lock (OdeLock)
|
||||||
|
{
|
||||||
|
IntPtr GroundGeom = IntPtr.Zero;
|
||||||
|
if (RegionTerrain.TryGetValue(pOffset, out GroundGeom))
|
||||||
|
{
|
||||||
|
RegionTerrain.Remove(pOffset);
|
||||||
|
if (GroundGeom != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
|
||||||
|
{
|
||||||
|
TerrainHeightFieldHeightsHandlers[GroundGeom].Free();
|
||||||
|
TerrainHeightFieldHeightsHandlers.Remove(GroundGeom);
|
||||||
|
TerrainHeightFieldHeights.Remove(GroundGeom);
|
||||||
|
}
|
||||||
|
d.SpaceRemove(StaticSpace, GroundGeom);
|
||||||
|
d.GeomDestroy(GroundGeom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
|
||||||
|
|
||||||
|
const int wrap = 0;
|
||||||
|
float thickness = hfmin;
|
||||||
|
if (thickness < 0)
|
||||||
|
thickness = 1;
|
||||||
|
|
||||||
|
GCHandle _heightmaphandler = GCHandle.Alloc(_heightmap, GCHandleType.Pinned);
|
||||||
|
|
||||||
|
d.GeomUbitTerrainDataBuild(HeightmapData, _heightmaphandler.AddrOfPinnedObject(), 0, 1.0f,
|
||||||
|
(int)heightmapWidthSamples, (int)heightmapHeightSamples,
|
||||||
|
thickness, wrap);
|
||||||
|
|
||||||
|
// d.GeomUbitTerrainDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
|
||||||
|
GroundGeom = d.CreateUbitTerrain(StaticSpace, HeightmapData, 1);
|
||||||
|
if (GroundGeom != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land));
|
||||||
|
d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space));
|
||||||
|
|
||||||
|
}
|
||||||
|
geom_name_map[GroundGeom] = "Terrain";
|
||||||
|
|
||||||
|
d.GeomSetPosition(GroundGeom, pOffset.X + (float)Constants.RegionSize * 0.5f, pOffset.Y + (float)Constants.RegionSize * 0.5f, 0);
|
||||||
|
RegionTerrain.Add(pOffset, GroundGeom, GroundGeom);
|
||||||
|
// TerrainHeightFieldHeights.Add(GroundGeom, ODElandMap);
|
||||||
|
TerrainHeightFieldHeights.Add(GroundGeom, _heightmap);
|
||||||
|
TerrainHeightFieldHeightsHandlers.Add(GroundGeom, _heightmaphandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public override void DeleteTerrain()
|
public override void DeleteTerrain()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -3176,17 +3176,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_host.IsRoot)
|
// new SL always returns object mass
|
||||||
{
|
// if (m_host.IsRoot)
|
||||||
|
// {
|
||||||
return m_host.ParentGroup.GetMass();
|
return m_host.ParentGroup.GetMass();
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
return m_host.GetMass();
|
// return m_host.GetMass();
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public LSL_Float llGetMassMKS()
|
||||||
|
{
|
||||||
|
return 100f * llGetMass();
|
||||||
|
}
|
||||||
|
|
||||||
public void llCollisionFilter(string name, string id, int accept)
|
public void llCollisionFilter(string name, string id, int accept)
|
||||||
{
|
{
|
||||||
m_host.AddScriptLPS(1);
|
m_host.AddScriptLPS(1);
|
||||||
|
@ -4959,7 +4966,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
{
|
{
|
||||||
float distance = (PusheePos - m_host.AbsolutePosition).Length();
|
float distance = (PusheePos - m_host.AbsolutePosition).Length();
|
||||||
float distance_term = distance * distance * distance; // Script Energy
|
float distance_term = distance * distance * distance; // Script Energy
|
||||||
float pusher_mass = m_host.GetMass();
|
// use total object mass and not part
|
||||||
|
float pusher_mass = m_host.ParentGroup.GetMass();
|
||||||
|
|
||||||
float PUSH_ATTENUATION_DISTANCE = 17f;
|
float PUSH_ATTENUATION_DISTANCE = 17f;
|
||||||
float PUSH_ATTENUATION_SCALE = 5f;
|
float PUSH_ATTENUATION_SCALE = 5f;
|
||||||
|
@ -9964,9 +9972,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
|
SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
|
||||||
if (obj != null)
|
if (obj != null)
|
||||||
return (double)obj.GetMass();
|
return (double)obj.GetMass();
|
||||||
|
*/
|
||||||
|
// return total object mass
|
||||||
|
SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
|
||||||
|
if (obj != null)
|
||||||
|
return (double)obj.GetMass();
|
||||||
|
|
||||||
// the object is null so the key is for an avatar
|
// the object is null so the key is for an avatar
|
||||||
ScenePresence avatar = World.GetScenePresence(key);
|
ScenePresence avatar = World.GetScenePresence(key);
|
||||||
if (avatar != null)
|
if (avatar != null)
|
||||||
|
|
|
@ -148,7 +148,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||||
LSL_Vector llGetLocalPos();
|
LSL_Vector llGetLocalPos();
|
||||||
LSL_Rotation llGetLocalRot();
|
LSL_Rotation llGetLocalRot();
|
||||||
LSL_Float llGetMass();
|
LSL_Float llGetMass();
|
||||||
void llGetNextEmail(string address, string subject);
|
LSL_Float llGetMassMKS();
|
||||||
|
void llGetNextEmail(string address, string subject);
|
||||||
LSL_String llGetNotecardLine(string name, int line);
|
LSL_String llGetNotecardLine(string name, int line);
|
||||||
LSL_Key llGetNumberOfNotecardLines(string name);
|
LSL_Key llGetNumberOfNotecardLines(string name);
|
||||||
LSL_Integer llGetNumberOfPrims();
|
LSL_Integer llGetNumberOfPrims();
|
||||||
|
|
|
@ -581,6 +581,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||||
return m_LSL_Functions.llGetMass();
|
return m_LSL_Functions.llGetMass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LSL_Float llGetMassMKS()
|
||||||
|
{
|
||||||
|
return m_LSL_Functions.llGetMassMKS();
|
||||||
|
}
|
||||||
|
|
||||||
public void llGetNextEmail(string address, string subject)
|
public void llGetNextEmail(string address, string subject)
|
||||||
{
|
{
|
||||||
m_LSL_Functions.llGetNextEmail(address, subject);
|
m_LSL_Functions.llGetNextEmail(address, subject);
|
||||||
|
|
Loading…
Reference in New Issue