From ad544bdd3d37700af7c8d05bafaed7cdd3dd3cd6 Mon Sep 17 00:00:00 2001
From: UbitUmarov
Date: Mon, 9 Apr 2012 18:03:37 +0100
Subject: sop.AddToPhysics(..) fixed and in use. For now it seems it needs to
set sop.PhysActor, so made it return void.
---
OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 410 ++++++++-------------
1 file changed, 147 insertions(+), 263 deletions(-)
(limited to 'OpenSim/Region')
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 969ddaf..d419710 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -122,6 +122,11 @@ namespace OpenSim.Region.Framework.Scenes
/// Denote all sides of the prim
///
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);
@@ -1821,18 +1826,20 @@ namespace OpenSim.Region.Framework.Scenes
///
///
///
+ ///
- 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)
return;
if (PhysicsShapeType == (byte)PhysShapeType.none)
return;
- bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0;
- bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0;
-
+ bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
+ bool isPhantom = (_ObjectFlags & (uint) PrimFlags.Phantom) != 0;
if (IsJoint())
{
@@ -1840,68 +1847,11 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
- // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored
-// if (VolumeDetectActive)
-// isPhantom = false;
-
- // 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
- // 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;
- }
- }
- }
+ if ((!isPhantom || isPhysical || _VolumeDetectActive) && !ParentGroup.IsAttachment
+ && !(Shape.PathCurve == (byte)Extrusion.Flexible))
+ AddToPhysics(isPhysical, isPhantom, building, true);
+ else
+ PhysActor = null; // just to be sure
}
}
@@ -4628,7 +4578,6 @@ namespace OpenSim.Region.Framework.Scenes
///
///
///
-// public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD)
public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
{
bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
@@ -4639,209 +4588,92 @@ namespace OpenSim.Region.Framework.Scenes
if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
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)
- {
AddFlag(PrimFlags.Physics);
-/*
- if (!wasUsingPhysics)
- {
- DoPhysicsPropertyUpdate(UsePhysics, false);
-
- if (!ParentGroup.IsDeleted)
- {
- if (LocalId == ParentGroup.RootPart.LocalId)
- {
- ParentGroup.CheckSculptAndLoad();
- }
- }
- }
- */
- }
else
- {
RemFlag(PrimFlags.Physics);
-/*
- if (wasUsingPhysics)
- {
- DoPhysicsPropertyUpdate(UsePhysics, false);
- }
-*/
- }
if (SetPhantom)
AddFlag(PrimFlags.Phantom);
else
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
- || (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);
Acceleration = new Vector3(0, 0, 0);
if (ParentGroup.RootPart == this)
AngularVelocity = new Vector3(0, 0, 0);
-
- if (PhysActor != null)
- {
- ParentGroup.Scene.RemovePhysicalPrim(1);
- RemoveFromPhysics();
- }
}
else
{
- if (ParentGroup.Scene == null)
- return;
-
if (ParentGroup.Scene.CollidablePrims)
{
- if (PhysActor == null)
+ if (pa == null)
{
- PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape(
- string.Format("{0}/{1}", Name, UUID),
- Shape,
- AbsolutePosition,
- Scale,
- GetWorldRotation(), //physics wants world rotation like all other functions send
- UsePhysics,
- SetPhantom,
- PhysicsShapeType,
- m_localId);
-
- PhysActor.SetMaterial(Material);
-
- // if root part apply vehicle
- if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
- m_vehicle.SetVehicle(PhysActor);
-
- DoPhysicsPropertyUpdate(UsePhysics, true);
-
- if (!ParentGroup.IsDeleted)
+ AddToPhysics(UsePhysics, SetPhantom, building , false);
+ pa = PhysActor;
+
+ if (pa != null)
{
- 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
{
DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
- if (!ParentGroup.IsDeleted)
- {
- if (LocalId == ParentGroup.RootPart.LocalId)
- {
- ParentGroup.CheckSculptAndLoad();
- }
- }
- }
- }
- }
+ if(VolumeDetectActive)
+ pa.SetVolumeDetect(1);
+ else
+ pa.SetVolumeDetect(0);
- 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 (pa.Building != building)
+ pa.Building = building;
+ }
}
- }
-
- 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());
// and last in case we have a new actor and not building
- if (pa != null && pa.Building != building)
- pa.Building = building;
+
if (ParentGroup != null)
{
ParentGroup.HasGroupChanged = true;
@@ -4853,48 +4685,104 @@ namespace OpenSim.Region.Framework.Scenes
///
/// Adds this part to the physics scene.
+ /// and sets the PhysActor property
///
- /// This method also sets the PhysActor property.
- /// Add this prim with a rigid body.
- ///
- /// The physics actor. null if there was a failure.
- ///
- private PhysicsActor AddToPhysics(bool rigidBody)
- {
+ /// Add this prim as physical.
+ /// Add this prim as phantom.
+ /// tells physics to delay full construction of object
+ /// applies velocities, force and torque
+ private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
+ {
PhysicsActor pa;
+ Vector3 velocity = Velocity;
+ Vector3 rotationalVelocity = AngularVelocity;;
+
try
{
pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
- string.Format("{0}/{1}", Name, UUID),
- Shape,
- AbsolutePosition,
- Scale,
- RotationOffset,
- rigidBody,
- m_localId);
+ string.Format("{0}/{1}", Name, UUID),
+ Shape,
+ AbsolutePosition,
+ Scale,
+ GetWorldRotation(),
+ isPhysical,
+ 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;
}
-
- // 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)
{
pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
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;
+ }
///
/// This removes the part from the physics scene.
@@ -5103,10 +4991,6 @@ namespace OpenSim.Region.Framework.Scenes
PhysicsActor pa = PhysActor;
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 (
// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
@@ -5114,7 +4998,7 @@ namespace OpenSim.Region.Framework.Scenes
// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
- ((AggregateScriptEvents & NeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
+ ((AggregateScriptEvents & PhyscicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
)
{
// subscribe to physics updates.
--
cgit v1.1
From 87fdb2ed7e27e9c161a4d10d9c5b9859dcde5b2d Mon Sep 17 00:00:00 2001
From: UbitUmarov
Date: Mon, 9 Apr 2012 20:53:29 +0100
Subject: llGetMass and llGetObjectMass (and push estimation) always use
object mass as in current SL ( push is what makes sense or impulse will
depend on what prim it is and not object). Added llGetMassMKS() that just
returns 100 x llGetMass() as it seems to be in SL.
---
.../Shared/Api/Implementation/LSL_Api.cs | 31 ++++++++++++++++------
.../ScriptEngine/Shared/Api/Interface/ILSL_Api.cs | 3 ++-
.../ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs | 5 ++++
3 files changed, 30 insertions(+), 9 deletions(-)
(limited to 'OpenSim/Region')
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index e71f027..2f61b70 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -3176,17 +3176,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
else
{
- if (m_host.IsRoot)
- {
+ // new SL always returns object mass
+// if (m_host.IsRoot)
+// {
return m_host.ParentGroup.GetMass();
- }
- else
- {
- return m_host.GetMass();
- }
+// }
+// else
+// {
+// return m_host.GetMass();
+// }
}
}
+
+ public LSL_Float llGetMassMKS()
+ {
+ return 100f * llGetMass();
+ }
+
public void llCollisionFilter(string name, string id, int accept)
{
m_host.AddScriptLPS(1);
@@ -4959,7 +4966,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
float distance = (PusheePos - m_host.AbsolutePosition).Length();
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_SCALE = 5f;
@@ -9964,9 +9972,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
try
{
+ /*
SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
if (obj != null)
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
ScenePresence avatar = World.GetScenePresence(key);
if (avatar != null)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index b976dc3..5c528977 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -148,7 +148,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
LSL_Vector llGetLocalPos();
LSL_Rotation llGetLocalRot();
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_Key llGetNumberOfNotecardLines(string name);
LSL_Integer llGetNumberOfPrims();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index bf58d13..70c5fcd 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -581,6 +581,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
return m_LSL_Functions.llGetMass();
}
+ public LSL_Float llGetMassMKS()
+ {
+ return m_LSL_Functions.llGetMassMKS();
+ }
+
public void llGetNextEmail(string address, string subject)
{
m_LSL_Functions.llGetNextEmail(address, subject);
--
cgit v1.1
From 39079a62c038986b20ccc3cf89a2e169f6e6135f Mon Sep 17 00:00:00 2001
From: UbitUmarov
Date: Mon, 9 Apr 2012 20:58:40 +0100
Subject: chODE and ubitODE always return prim mass (they where returning
object mass on physical prims) so SOG can do the total add. (ubitODE as more
code to use a simpler terrain geom on a modified ode lib but should do
autodetect and work with normal lib).
---
OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 11 +-
OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs | 2 +-
OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs | 53 +++-
OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs | 318 ++++++++++++++++++-----
4 files changed, 315 insertions(+), 69 deletions(-)
(limited to 'OpenSim/Region')
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
index 3e2b71c..77ea2af 100644
--- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
@@ -179,6 +179,8 @@ namespace OpenSim.Region.Physics.OdePlugin
public bool m_outofBounds;
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_taintshapetype;
@@ -538,7 +540,11 @@ namespace OpenSim.Region.Physics.OdePlugin
public override float Mass
{
- get { return CalculateMass(); }
+ get
+ {
+ CalculateMass();
+ return m_primMass;
+ }
}
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
bool HasChildPrim = false;
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
index c4dc793..f739183 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
@@ -395,7 +395,7 @@ namespace OpenSim.Region.Physics.OdePlugin
public override float Mass
{
- get { return _mass; }
+ get { return primMass; }
}
public override Vector3 Force
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs
index 2b6bc59..f5129cb 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs
@@ -107,16 +107,17 @@ namespace OdeAPI
ConvexClass,
GeomTransformClass,
TriMeshClass,
- HeightfieldClass,
+ HeightfieldClass,
FirstSpaceClass,
SimpleSpaceClass = FirstSpaceClass,
HashSpaceClass,
QuadTreeSpaceClass,
LastSpaceClass = QuadTreeSpaceClass,
+ UbitTerrainClass,
FirstUserClass,
LastUserClass = FirstUserClass + MaxUserClasses - 1,
NumClasses,
- MaxUserClasses = 4
+ MaxUserClasses = 5
}
public enum JointType : int
@@ -201,8 +202,11 @@ namespace OdeAPI
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void GeomDtorFn(IntPtr o);
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate dReal HeightfieldGetHeight(IntPtr p_user_data, int x, int z);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ 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)]
public delegate void NearCallback(IntPtr data, IntPtr geom1, IntPtr geom2);
@@ -729,6 +733,18 @@ namespace OdeAPI
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]
public static extern IntPtr CreateiGeom(int classnum);
public static IntPtr CreateGeom(int classnum)
@@ -964,6 +980,8 @@ namespace OdeAPI
dReal width, dReal depth, int widthSamples, int depthSamples,
dReal scale, dReal offset, dReal thickness, int bWrap);
+
+
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity]
public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, double[] pHeightData, int bCopyHeightData,
dReal width, dReal depth, int widthSamples, int depthSamples,
@@ -989,6 +1007,33 @@ namespace OdeAPI
[DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldSetHeightfieldData"), SuppressUnmanagedCodeSecurity]
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]
public static extern bool GeomIsEnabled(IntPtr geom);
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
index 1a6907d..3e0ccef 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
@@ -156,6 +156,7 @@ namespace OpenSim.Region.Physics.OdePlugin
private readonly ILog m_log;
// private Dictionary m_storedCollisions = new Dictionary();
+ public bool OdeUbitLib = false;
// private int threadid = 0;
private Random fluidRandomizer = new Random(Environment.TickCount);
@@ -374,7 +375,14 @@ namespace OpenSim.Region.Physics.OdePlugin
mesher = meshmerizer;
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)
{
@@ -527,13 +535,24 @@ namespace OpenSim.Region.Physics.OdePlugin
// 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)
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();
- newcontact.geom.depth = contactGeom.depth;
+ newcontact.geom.depth = depth;
newcontact.geom.g1 = contactGeom.g1;
newcontact.geom.g2 = contactGeom.g2;
newcontact.geom.pos = contactGeom.pos;
@@ -692,6 +711,10 @@ namespace OpenSim.Region.Physics.OdePlugin
float bounce = 0;
float cfm = 0.0001f;
float erp = 0.1f;
+ float erpscale = 1.0f;
+ float dscale = 1.0f;
+ bool IgnoreNegSides = false;
+
ContactData contactdata1 = new ContactData(0, 0, false);
ContactData contactdata2 = new ContactData(0, 0, false);
@@ -781,10 +804,14 @@ namespace OpenSim.Region.Physics.OdePlugin
cfm = p1.Mass;
if (cfm > p2.Mass)
cfm = p2.Mass;
- cfm = (float)Math.Sqrt(cfm);
- cfm *= 0.0001f;
- if (cfm > 0.8f)
- cfm = 0.8f;
+ dscale = 10 / cfm;
+ dscale = (float)Math.Sqrt(dscale);
+ if (dscale > 1.0f)
+ 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))
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)
mu *= frictionMovementMult;
p1.CollidingGround = true;
+
cfm = p1.Mass;
- cfm = (float)Math.Sqrt(cfm);
- cfm *= 0.0001f;
- if (cfm > 0.8f)
- cfm = 0.8f;
+ dscale = 10 / cfm;
+ dscale = (float)Math.Sqrt(dscale);
+ if (dscale > 1.0f)
+ 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")
@@ -830,11 +868,21 @@ namespace OpenSim.Region.Physics.OdePlugin
p2.getContactData(ref contactdata2);
bounce = contactdata2.bounce * TerrainBounce;
mu = (float)Math.Sqrt(contactdata2.mu * TerrainFriction);
+
cfm = p2.Mass;
- cfm = (float)Math.Sqrt(cfm);
- cfm *= 0.0001f;
- if (cfm > 0.8f)
- cfm = 0.8f;
+ dscale = 10 / cfm;
+ dscale = (float)Math.Sqrt(dscale);
+
+ 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)
mu *= frictionMovementMult;
@@ -862,39 +910,45 @@ namespace OpenSim.Region.Physics.OdePlugin
int i = 0;
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)
+ {
+ if (++i >= count)
+ break;
- erp = curContact.depth;
- if (erp < minERP)
- erp = minERP;
- else if (erp > MaxERP)
- erp = MaxERP;
+ if (!GetCurContactGeom(i, ref curContact))
+ break;
+ }
+ else
- Joint = CreateContacJoint(ref curContact, mu, bounce,cfm,erp);
- d.JointAttach(Joint, b1, b2);
+ {
+ 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 (++m_global_contactcount >= maxContactsbeforedeath)
- break;
+ Joint = CreateContacJoint(ref curContact, mu, bounce, cfm, erpscale, dscale);
+ d.JointAttach(Joint, b1, b2);
- if(++i >= count)
- break;
+ if (++m_global_contactcount >= maxContactsbeforedeath)
+ break;
- if (!GetCurContactGeom(i, ref curContact))
- break;
+ if (++i >= count)
+ 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;
+ 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)
{
- // 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 offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
+
IntPtr heightFieldGeom = IntPtr.Zero;
// 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
- // we still have square fixed size regions
- // 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
+ if (OdeUbitLib)
{
- iy = regsize - 1;
- dy = 0;
- }
- if (y < regsize - 1)
- {
- ix = (int)y;
- dx = y - (float)ix;
+ if (x < regsize - 1)
+ {
+ ix = (int)x;
+ dx = x - (float)ix;
+ }
+ else // out world use external height
+ {
+ ix = regsize - 1;
+ dx = 0;
+ }
+ if (y < regsize - 1)
+ {
+ iy = (int)y;
+ dy = y - (float)iy;
+ }
+ else
+ {
+ iy = regsize - 1;
+ dy = 0;
+ }
}
+
else
{
- ix = regsize - 1;
- dx = 0;
+ // we still have square fixed size regions
+ // 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;
@@ -1951,6 +2031,8 @@ namespace OpenSim.Region.Physics.OdePlugin
return h0 + h1 + h2;
}
+
+
public override void SetTerrain(float[] heightMap)
{
if (m_worldOffset != Vector3.Zero && m_parentScene != null)
@@ -1972,7 +2054,15 @@ namespace OpenSim.Region.Physics.OdePlugin
}
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
// 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()
{
}
--
cgit v1.1
From c4a9eae961030280473f6df77e59cb53865535b6 Mon Sep 17 00:00:00 2001
From: UbitUmarov
Date: Mon, 9 Apr 2012 23:33:42 +0100
Subject: make llGetGeometricCenter() work as in current SL. Now this is not
real geom center but a average of positions relative to root prim ignoring
prims details, so no need to use physics engine.
---
.../Region/Framework/Scenes/SceneObjectGroup.cs | 30 +++++++++++++++++++++-
OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 29 ++++++++++++++-------
2 files changed, 49 insertions(+), 10 deletions(-)
(limited to 'OpenSim/Region')
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 107d9b6..3fd1f5e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -3955,7 +3955,35 @@ 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()
{
float retmass = 0f;
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index d419710..511ab19 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -2260,18 +2260,29 @@ namespace OpenSim.Region.Framework.Scenes
public Vector3 GetGeometricCenter()
{
- PhysicsActor pa = PhysActor;
-
- if (pa != null)
- {
- Vector3 vtmp = pa.CenterOfMass;
- return vtmp;
- }
- else
+ // 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
+ if (ParentGroup.IsDeleted)
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;
--
cgit v1.1