diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index bf4d60cd61..77658efad5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -5010,6 +5010,47 @@ namespace OpenSim.Region.Framework.Scenes
return Ptot;
}
+ public void GetInertiaData(out float TotalMass, out Vector3 CenterOfMass, out Vector3 Inertia, out Vector4 aux )
+ {
+ PhysicsActor pa = RootPart.PhysActor;
+
+ if(((RootPart.Flags & PrimFlags.Physics) !=0) && pa !=null)
+ {
+ PhysicsInertiaData inertia;
+
+ inertia = pa.GetInertiaData();
+
+ TotalMass = inertia.TotalMass;
+ CenterOfMass = inertia.CenterOfMass;
+ Inertia = inertia.Inertia;
+ aux = inertia.InertiaRotation;
+
+ return;
+ }
+
+ TotalMass = GetMass();
+ CenterOfMass = GetCenterOfMass() - AbsolutePosition;
+ CenterOfMass *= Quaternion.Conjugate(RootPart.RotationOffset);
+ Inertia = Vector3.Zero;
+ aux = Vector4.Zero;
+ }
+
+ public void SetInertiaData(float TotalMass, Vector3 CenterOfMass, Vector3 Inertia, Vector4 aux )
+ {
+ PhysicsActor pa = RootPart.PhysActor;
+
+ if(pa !=null)
+ {
+ PhysicsInertiaData inertia = new PhysicsInertiaData();
+ inertia.TotalMass = TotalMass;
+ inertia.CenterOfMass = CenterOfMass;
+ inertia.Inertia = Inertia;
+ inertia.InertiaRotation = aux;
+ pa.SetInertiaData(inertia);
+ }
+ }
+
+
///
/// Set the user group to which this scene object belongs.
///
diff --git a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
index 33f033759b..ad9b28f8f1 100644
--- a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
+++ b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
@@ -55,6 +55,28 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
Absolute
}
+ public class PhysicsInertiaData
+ {
+ public float TotalMass; // the total mass of a linkset
+ public Vector3 CenterOfMass; // the center of mass position relative to root part position
+ public Vector3 Inertia; // (Ixx, Iyy, Izz) moment of inertia relative to center of mass and principal axis in local coords
+ public Vector4 InertiaRotation; // if principal axis don't match local axis, the principal axis rotation
+ // or the upper triangle of the inertia tensor
+ // Ixy (= Iyx), Ixz (= Izx), Iyz (= Izy))
+
+ public PhysicsInertiaData()
+ {
+ }
+
+ public PhysicsInertiaData(PhysicsInertiaData source)
+ {
+ TotalMass = source.TotalMass;
+ CenterOfMass = source.CenterOfMass;
+ Inertia = source.Inertia;
+ InertiaRotation = source.InertiaRotation;
+ }
+ }
+
public struct CameraData
{
public Quaternion CameraRotation;
@@ -463,6 +485,20 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
public virtual void AddCollisionEvent(uint CollidedWith, ContactPoint contact) { }
+ public virtual PhysicsInertiaData GetInertiaData()
+ {
+ PhysicsInertiaData data = new PhysicsInertiaData();
+ data.TotalMass = this.Mass;
+ data.CenterOfMass = CenterOfMass - Position;
+ data.Inertia = Vector3.Zero;
+ data.InertiaRotation = Vector4.Zero;
+ return data;
+ }
+
+ public virtual void SetInertiaData(PhysicsInertiaData inertia)
+ {
+ }
+
// Warning in a parent part it returns itself, not null
public virtual PhysicsActor ParentActor { get { return this; } }
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
index 45ef273bf2..d560b4124b 100644
--- a/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
@@ -182,14 +182,16 @@ namespace OpenSim.Region.PhysicsModule.ubOde
private float m_streamCost;
public d.Mass primdMass; // prim inertia information on it's own referencial
+ private PhysicsInertiaData m_InertiaOverride;
float primMass; // prim own mass
float primVolume; // prim own volume;
- float _mass; // object mass acording to case
+ float m_mass; // object mass acording to case
public int givefakepos;
private Vector3 fakepos;
public int givefakeori;
private Quaternion fakeori;
+ private PhysicsInertiaData m_fakeInertiaOverride;
private int m_eventsubscription;
private int m_cureventsubscription;
@@ -465,10 +467,110 @@ namespace OpenSim.Region.PhysicsModule.ubOde
}
}
+ public override PhysicsInertiaData GetInertiaData()
+ {
+ PhysicsInertiaData inertia;
+ if(childPrim)
+ {
+ if(_parent != null)
+ return _parent.GetInertiaData();
+ else
+ {
+ inertia = new PhysicsInertiaData();
+ inertia.TotalMass = -1;
+ return inertia;
+ }
+ }
+
+ inertia = new PhysicsInertiaData();
+
+ // double buffering
+ if(m_fakeInertiaOverride != null)
+ {
+ d.Mass objdmass = new d.Mass();
+ objdmass.I.M00 = m_fakeInertiaOverride.Inertia.X;
+ objdmass.I.M11 = m_fakeInertiaOverride.Inertia.Y;
+ objdmass.I.M22 = m_fakeInertiaOverride.Inertia.Z;
+
+ objdmass.mass = m_fakeInertiaOverride.TotalMass;
+
+ if(Math.Abs(m_fakeInertiaOverride.InertiaRotation.W) < 0.999)
+ {
+ d.Matrix3 inertiarotmat = new d.Matrix3();
+ d.Quaternion inertiarot = new d.Quaternion();
+
+ inertiarot.X = m_fakeInertiaOverride.InertiaRotation.X;
+ inertiarot.Y = m_fakeInertiaOverride.InertiaRotation.Y;
+ inertiarot.Z = m_fakeInertiaOverride.InertiaRotation.Z;
+ inertiarot.W = m_fakeInertiaOverride.InertiaRotation.W;
+ d.RfromQ(out inertiarotmat, ref inertiarot);
+ d.MassRotate(ref objdmass, ref inertiarotmat);
+ }
+
+ inertia.TotalMass = m_fakeInertiaOverride.TotalMass;
+ inertia.CenterOfMass = m_fakeInertiaOverride.CenterOfMass;
+ inertia.Inertia.X = objdmass.I.M00;
+ inertia.Inertia.Y = objdmass.I.M11;
+ inertia.Inertia.Z = objdmass.I.M22;
+ inertia.InertiaRotation.X = objdmass.I.M01;
+ inertia.InertiaRotation.Y = objdmass.I.M02;
+ inertia.InertiaRotation.Z = objdmass.I.M12;
+ return inertia;
+ }
+
+ inertia.TotalMass = m_mass;
+
+ if(Body == IntPtr.Zero || prim_geom == IntPtr.Zero)
+ {
+ inertia.CenterOfMass = Vector3.Zero;
+ inertia.Inertia = Vector3.Zero;
+ inertia.InertiaRotation = Vector4.Zero;
+ return inertia;
+ }
+
+ d.Vector3 dtmp;
+ d.Mass m = new d.Mass();
+ lock(_parent_scene.OdeLock)
+ {
+ d.AllocateODEDataForThread(0);
+ dtmp = d.GeomGetOffsetPosition(prim_geom);
+ d.BodyGetMass(Body, out m);
+ }
+
+ Vector3 cm = new Vector3(-dtmp.X, -dtmp.Y, -dtmp.Z);
+ inertia.CenterOfMass = cm;
+ inertia.Inertia = new Vector3(m.I.M00, m.I.M11, m.I.M22);
+ inertia.InertiaRotation = new Vector4(m.I.M01, m.I.M02 , m.I.M12, 0);
+
+ return inertia;
+ }
+
+ public override void SetInertiaData(PhysicsInertiaData inertia)
+ {
+ if(childPrim)
+ {
+ if(_parent != null)
+ _parent.SetInertiaData(inertia);
+ return;
+ }
+
+ if(inertia.TotalMass > 0)
+ m_fakeInertiaOverride = new PhysicsInertiaData(inertia);
+ else
+ m_fakeInertiaOverride = null;
+
+ if (inertia.TotalMass > _parent_scene.maximumMassObject)
+ inertia.TotalMass = _parent_scene.maximumMassObject;
+ AddChange(changes.SetInertia,(object)m_fakeInertiaOverride);
+ }
+
public override Vector3 CenterOfMass
{
get
{
+ if(!childPrim && m_fakeInertiaOverride != null)
+ return m_fakeInertiaOverride.CenterOfMass;
+
lock (_parent_scene.OdeLock)
{
d.AllocateODEDataForThread(0);
@@ -922,8 +1024,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde
{
float old = m_density;
m_density = value / 100f;
- if(m_density != old)
- UpdatePrimBodyData();
+ // if(m_density != old)
+ // UpdatePrimBodyData();
}
}
public override float GravModifier
@@ -1716,26 +1818,29 @@ namespace OpenSim.Region.PhysicsModule.ubOde
m_log.Warn("[PHYSICS]: MakeBody root geom already had a body");
}
+ bool noInertiaOverride = (m_InertiaOverride == null);
+
+ Body = d.BodyCreate(_parent_scene.world);
+
d.Matrix3 mymat = new d.Matrix3();
d.Quaternion myrot = new d.Quaternion();
d.Mass objdmass = new d.Mass { };
- Body = d.BodyCreate(_parent_scene.world);
-
- objdmass = primdMass;
-
- // rotate inertia
myrot.X = _orientation.X;
myrot.Y = _orientation.Y;
myrot.Z = _orientation.Z;
myrot.W = _orientation.W;
-
d.RfromQ(out mymat, ref myrot);
- d.MassRotate(ref objdmass, ref mymat);
// set the body rotation
d.BodySetRotation(Body, ref mymat);
+ if(noInertiaOverride)
+ {
+ objdmass = primdMass;
+ d.MassRotate(ref objdmass, ref mymat);
+ }
+
// recompute full object inertia if needed
if (childrenPrim.Count > 0)
{
@@ -1758,27 +1863,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde
continue;
}
- tmpdmass = prm.primdMass;
-
- // apply prim current rotation to inertia
quat.X = prm._orientation.X;
quat.Y = prm._orientation.Y;
quat.Z = prm._orientation.Z;
quat.W = prm._orientation.W;
d.RfromQ(out mat, ref quat);
- d.MassRotate(ref tmpdmass, ref mat);
- Vector3 ppos = prm._position;
- ppos.X -= rcm.X;
- ppos.Y -= rcm.Y;
- ppos.Z -= rcm.Z;
- // refer inertia to root prim center of mass position
- d.MassTranslate(ref tmpdmass,
- ppos.X,
- ppos.Y,
- ppos.Z);
-
- d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
// fix prim colision cats
if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero)
@@ -1791,6 +1881,24 @@ namespace OpenSim.Region.PhysicsModule.ubOde
d.GeomSetBody(prm.prim_geom, Body);
prm.Body = Body;
d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation
+
+ if(noInertiaOverride)
+ {
+ tmpdmass = prm.primdMass;
+
+ d.MassRotate(ref tmpdmass, ref mat);
+ Vector3 ppos = prm._position;
+ ppos.X -= rcm.X;
+ ppos.Y -= rcm.Y;
+ ppos.Z -= rcm.Z;
+ // refer inertia to root prim center of mass position
+ d.MassTranslate(ref tmpdmass,
+ ppos.X,
+ ppos.Y,
+ ppos.Z);
+
+ d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
+ }
}
}
}
@@ -1799,19 +1907,60 @@ namespace OpenSim.Region.PhysicsModule.ubOde
// associate root geom with body
d.GeomSetBody(prim_geom, Body);
- d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z);
+ if(noInertiaOverride)
+ d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z);
+ else
+ {
+ Vector3 ncm = m_InertiaOverride.CenterOfMass * _orientation;
+ d.BodySetPosition(Body,
+ _position.X + ncm.X,
+ _position.Y + ncm.Y,
+ _position.Z + ncm.Z);
+ }
+
d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z);
- d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
- myrot.X = -myrot.X;
- myrot.Y = -myrot.Y;
- myrot.Z = -myrot.Z;
+ if(noInertiaOverride)
+ {
+ d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
+ myrot.X = -myrot.X;
+ myrot.Y = -myrot.Y;
+ myrot.Z = -myrot.Z;
- d.RfromQ(out mymat, ref myrot);
- d.MassRotate(ref objdmass, ref mymat);
+ d.RfromQ(out mymat, ref myrot);
+ d.MassRotate(ref objdmass, ref mymat);
- d.BodySetMass(Body, ref objdmass);
- _mass = objdmass.mass;
+ d.BodySetMass(Body, ref objdmass);
+ m_mass = objdmass.mass;
+ }
+ else
+ {
+ objdmass.c.X = 0;
+ objdmass.c.Y = 0;
+ objdmass.c.Z = 0;
+
+ objdmass.I.M00 = m_InertiaOverride.Inertia.X;
+ objdmass.I.M11 = m_InertiaOverride.Inertia.Y;
+ objdmass.I.M22 = m_InertiaOverride.Inertia.Z;
+
+ objdmass.mass = m_InertiaOverride.TotalMass;
+
+ if(Math.Abs(m_InertiaOverride.InertiaRotation.W) < 0.999)
+ {
+ d.Matrix3 inertiarotmat = new d.Matrix3();
+ d.Quaternion inertiarot = new d.Quaternion();
+
+ inertiarot.X = m_InertiaOverride.InertiaRotation.X;
+ inertiarot.Y = m_InertiaOverride.InertiaRotation.Y;
+ inertiarot.Z = m_InertiaOverride.InertiaRotation.Z;
+ inertiarot.W = m_InertiaOverride.InertiaRotation.W;
+ d.RfromQ(out inertiarotmat, ref inertiarot);
+ d.MassRotate(ref objdmass, ref inertiarotmat);
+ }
+ d.BodySetMass(Body, ref objdmass);
+
+ m_mass = objdmass.mass;
+ }
// disconnect from world gravity so we can apply buoyancy
d.BodySetGravityMode(Body, false);
@@ -1990,7 +2139,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
SetInStaticSpace(prm);
}
prm.Body = IntPtr.Zero;
- prm._mass = prm.primMass;
+ prm.m_mass = prm.primMass;
prm.m_collisionscore = 0;
}
}
@@ -2004,7 +2153,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
}
Body = IntPtr.Zero;
}
- _mass = primMass;
+ m_mass = primMass;
m_collisionscore = 0;
}
@@ -2081,7 +2230,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
d.BodySetMass(Body, ref objdmass);
- _mass = objdmass.mass;
+ m_mass = objdmass.mass;
}
private void FixInertia(Vector3 NewPos)
@@ -2145,7 +2294,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
d.BodySetMass(Body, ref objdmass);
- _mass = objdmass.mass;
+ m_mass = objdmass.mass;
}
private void FixInertia(Quaternion newrot)
@@ -2211,7 +2360,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
d.BodySetMass(Body, ref objdmass);
- _mass = objdmass.mass;
+ m_mass = objdmass.mass;
}
@@ -2226,7 +2375,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (primMass > _parent_scene.maximumMassObject)
primMass = _parent_scene.maximumMassObject;
- _mass = primMass; // just in case
+ m_mass = primMass; // just in case
d.MassSetBoxTotal(out primdMass, primMass, 2.0f * m_OBB.X, 2.0f * m_OBB.Y, 2.0f * m_OBB.Z);
@@ -3306,6 +3455,15 @@ namespace OpenSim.Region.PhysicsModule.ubOde
m_useHoverPID = active;
}
+ private void changeInertia(PhysicsInertiaData inertia)
+ {
+ m_InertiaOverride = inertia;
+
+ if (Body != IntPtr.Zero)
+ DestroyBody();
+ MakeBody();
+ }
+
#endregion
public void Move()
@@ -3346,7 +3504,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
float fy = 0;
float fz = 0;
- float m_mass = _mass;
+ float mass = m_mass;
if (m_usePID && m_PIDTau > 0)
{
@@ -3453,9 +3611,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde
fz = _parent_scene.gravityz * b;
}
- fx *= m_mass;
- fy *= m_mass;
- fz *= m_mass;
+ fx *= mass;
+ fy *= mass;
+ fz *= mass;
// constant force
fx += m_force.X;
@@ -3941,6 +4099,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde
changePIDHoverActive((bool)arg);
break;
+ case changes.SetInertia:
+ changeInertia((PhysicsInertiaData) arg);
+ break;
+
case changes.Null:
donullchange();
break;
@@ -3957,7 +4119,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde
_parent_scene.AddChange((PhysicsActor) this, what, arg);
}
-
private struct strVehicleBoolParam
{
public int param;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 4c3f7eeec5..6c094ee29d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -4404,5 +4404,218 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.ScriptSetVolumeDetect(detect != 0);
}
+ ///
+ /// Get inertial data
+ ///
+ ///
+ ///
+ ///
+ /// a LSL list with contents:
+ /// LSL_Float mass, the total mass of a linkset
+ /// LSL_Vector CenterOfMass, center mass relative to root prim
+ /// LSL_Vector Inertia, elements of diagonal of inertia Ixx,Iyy,Izz divided by total mass
+ /// LSL_Vector aux, elements of upper triagle of inertia Ixy (= Iyx), Ixz (= Izx), Iyz(= Izy) divided by total mass
+ ///
+ public LSL_List osGetInertiaData()
+ {
+ LSL_List result = new LSL_List();
+ float TotalMass;
+ Vector3 CenterOfMass;
+ Vector3 Inertia;
+ Vector4 aux;
+
+ SceneObjectGroup sog = m_host.ParentGroup;
+ if(sog== null || sog.IsDeleted)
+ return result;
+
+ sog.GetInertiaData(out TotalMass, out CenterOfMass, out Inertia, out aux );
+ if(TotalMass > 0)
+ {
+ float t = 1.0f/TotalMass;
+ Inertia.X *= t;
+ Inertia.Y *= t;
+ Inertia.Z *= t;
+
+ aux.X *= t;
+ aux.Y *= t;
+ aux.Z *= t;
+ }
+
+ result.Add(new LSL_Float(TotalMass));
+ result.Add(new LSL_Vector(CenterOfMass.X, CenterOfMass.Y, CenterOfMass.Z));
+ result.Add(new LSL_Vector(Inertia.X, Inertia.Y, Inertia.Z));
+ result.Add(new LSL_Vector(aux.X, aux.Y, aux.Z));
+ return result;
+ }
+
+ ///
+ /// set inertial data
+ /// replaces the automatic calculation of mass, center of mass and inertia
+ ///
+ ///
+ /// total mass of linkset
+ /// location of center of mass relative to root prim in local coords
+ /// moment of inertia relative to principal axis and center of mass,Ixx, Iyy, Izz divided by mass
+ /// rotation of the inertia, relative to local axis
+ ///
+ /// the inertia argument is is inertia divided by mass, so corresponds only to the geometric distribution of mass and both can be changed independently.
+ ///
+
+ public void osSetInertia(LSL_Float mass, LSL_Vector centerOfMass, LSL_Vector principalInertiaScaled, LSL_Rotation lslrot)
+ {
+ SceneObjectGroup sog = m_host.ParentGroup;
+ if(sog== null || sog.IsDeleted)
+ return;
+
+ if(mass < 0 || principalInertiaScaled.x < 0 || principalInertiaScaled.y < 0 || principalInertiaScaled.z < 0)
+ return;
+
+ // need more checks
+
+ Vector3 CenterOfMass = new Vector3((float)centerOfMass.x,(float)centerOfMass.y,(float)centerOfMass.z);
+ Vector3 Inertia;
+ float m = (float)mass;
+
+ Inertia.X = m * (float)principalInertiaScaled.x;
+ Inertia.Y = m * (float)principalInertiaScaled.y;
+ Inertia.Z = m * (float)principalInertiaScaled.z;
+
+ Vector4 rot = new Vector4((float)lslrot.x, (float)lslrot.y, (float)lslrot.y, (float)lslrot.s);
+ rot.Normalize();
+
+ sog.SetInertiaData(m, CenterOfMass, Inertia, rot );
+ }
+
+ ///
+ /// set inertial data as a sphere
+ /// replaces the automatic calculation of mass, center of mass and inertia
+ ///
+ ///
+ /// total mass of linkset
+ /// size of the Box
+ /// location of center of mass relative to root prim in local coords
+ /// rotation of the box, and so inertia, relative to local axis
+ ///
+ ///
+ public void osSetInertiaAsBox(LSL_Float mass, LSL_Vector boxSize, LSL_Vector centerOfMass, LSL_Rotation lslrot)
+ {
+ SceneObjectGroup sog = m_host.ParentGroup;
+ if(sog== null || sog.IsDeleted)
+ return;
+
+ if(mass < 0)
+ return;
+
+ // need more checks
+
+ Vector3 CenterOfMass = new Vector3((float)centerOfMass.x,(float)centerOfMass.y,(float)centerOfMass.z);
+ Vector3 Inertia;
+ float lx = (float)boxSize.x;
+ float ly = (float)boxSize.y;
+ float lz = (float)boxSize.z;
+ float m = (float)mass;
+ float t = m / 12.0f;
+
+ Inertia.X = t * (ly*ly + lz*lz);
+ Inertia.Y = t * (lx*lx + lz*lz);
+ Inertia.Z = t * (lx*lx + ly*ly);
+
+ Vector4 rot = new Vector4((float)lslrot.x, (float)lslrot.y, (float)lslrot.z, (float)lslrot.s);
+ rot.Normalize();
+
+ sog.SetInertiaData(m, CenterOfMass, Inertia, rot );
+ }
+
+ ///
+ /// set inertial data as a sphere
+ /// replaces the automatic calculation of mass, center of mass and inertia
+ ///
+ ///
+ /// total mass of linkset
+ /// radius of the sphere
+ /// location of center of mass relative to root prim in local coords
+ ///
+ ///
+ public void osSetInertiaAsSphere(LSL_Float mass, LSL_Float radius, LSL_Vector centerOfMass)
+ {
+ SceneObjectGroup sog = m_host.ParentGroup;
+ if(sog== null || sog.IsDeleted)
+ return;
+
+ if(mass < 0)
+ return;
+
+ // need more checks
+
+ Vector3 CenterOfMass = new Vector3((float)centerOfMass.x,(float)centerOfMass.y,(float)centerOfMass.z);
+ Vector3 Inertia;
+ float r = (float)radius;
+ float m = (float)mass;
+ float t = 0.4f * m * r * r;
+
+ Inertia.X = t;
+ Inertia.Y = t;
+ Inertia.Z = t;
+
+ sog.SetInertiaData(m, CenterOfMass, Inertia, new Vector4(0f, 0f, 0f,1.0f));
+ }
+
+ ///
+ /// set inertial data as a cylinder
+ /// replaces the automatic calculation of mass, center of mass and inertia
+ ///
+ ///
+ /// total mass of linkset
+ /// radius of the cylinder
+ /// lenght of the cylinder
+ /// location of center of mass relative to root prim in local coords
+ /// rotation of the cylinder, and so inertia, relative to local axis
+ ///
+ /// cylinder axis aligned with Z axis. For other orientations provide the rotation.
+ ///
+ public void osSetInertiaAsCylinder(LSL_Float mass, LSL_Float radius, LSL_Float lenght, LSL_Vector centerOfMass, LSL_Rotation lslrot)
+ {
+ SceneObjectGroup sog = m_host.ParentGroup;
+ if(sog== null || sog.IsDeleted)
+ return;
+
+ if(mass < 0)
+ return;
+
+ // need more checks
+
+ Vector3 CenterOfMass = new Vector3((float)centerOfMass.x,(float)centerOfMass.y,(float)centerOfMass.z);
+ Vector3 Inertia;
+ float m = (float)mass;
+ float r = (float)radius;
+ r *= r;
+ Inertia.Z = 0.5f * m * r;
+ float t = (float)lenght;
+ t *= t;
+ t += 3.0f * r;
+ t *= 8.333333e-2f * m;
+
+ Inertia.X = t;
+ Inertia.Y = t;
+
+ Vector4 rot = new Vector4((float)lslrot.x, (float)lslrot.y, (float)lslrot.z, (float)lslrot.s);
+ rot.Normalize();
+
+ sog.SetInertiaData(m, CenterOfMass, Inertia, rot);
+ }
+
+ ///
+ /// removes inertial data manual override
+ /// default automatic calculation is used again
+ ///
+ ///
+ public void osClearInertia()
+ {
+ SceneObjectGroup sog = m_host.ParentGroup;
+ if(sog== null || sog.IsDeleted)
+ return;
+
+ sog.SetInertiaData(-1, Vector3.Zero, Vector3.Zero, Vector4.Zero );
+ }
}
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index bee060ad4c..f76ff7f350 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -38,6 +38,7 @@ using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
+
namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
{
///
@@ -486,6 +487,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
LSL_String osRequestURL(LSL_List options);
LSL_String osRequestSecureURL(LSL_List options);
void osCollisionSound(string impact_sound, double impact_volume);
+
void osVolumeDetect(int detect);
+
+ LSL_List osGetInertiaData();
+ void osClearInertia();
+ void osSetInertiaAsBox(LSL_Float mass, vector boxSize, vector centerOfMass, rotation rot);
+ void osSetInertiaAsSphere(LSL_Float mass, LSL_Float radius, vector centerOfMass);
+ void osSetInertiaAsCylinder(LSL_Float mass, LSL_Float radius, LSL_Float lenght, vector centerOfMass,rotation lslrot);
}
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index 6164734789..09337e5967 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -1114,5 +1114,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
{
m_OSSL_Functions.osVolumeDetect(detect);
}
+
+ public LSL_List osGetInertiaData()
+ {
+ return m_OSSL_Functions.osGetInertiaData();
+ }
+
+ public void osSetInertiaAsBox(LSL_Float mass, vector boxSize, vector centerOfMass, rotation rot)
+ {
+ m_OSSL_Functions.osSetInertiaAsBox(mass, boxSize, centerOfMass, rot);
+ }
+
+ public void osSetInertiaAsSphere(LSL_Float mass, LSL_Float radius, vector centerOfMass)
+ {
+ m_OSSL_Functions.osSetInertiaAsSphere(mass, radius, centerOfMass);
+ }
+
+ public void osSetInertiaAsCylinder(LSL_Float mass, LSL_Float radius, LSL_Float lenght, vector centerOfMass,rotation lslrot)
+ {
+ m_OSSL_Functions.osSetInertiaAsCylinder( mass, radius, lenght, centerOfMass, lslrot);
+ }
+
+ public void osClearInertia()
+ {
+ m_OSSL_Functions.osClearInertia();
+ }
+
}
}