From 6a35a965ff7085b5962745437a10d798c0fb611d Mon Sep 17 00:00:00 2001
From: UbitUmarov
Date: Fri, 31 Mar 2017 20:55:48 +0100
Subject: add OSSL functions to override linksets total mass, center of mass
and inertia. replacing the crude automatic estimation based on prims known to
physics and density. Changed parameters are still not saved, and are lost on
region crossings. only suported by UbODE. EXPERIMENTAL feature, only test it
for now.. don't try to use in products.
---
.../Shared/Api/Implementation/OSSL_Api.cs | 213 +++++++++++++++++++++
.../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 8 +
.../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 26 +++
3 files changed, 247 insertions(+)
(limited to 'OpenSim/Region/ScriptEngine')
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 4c3f7ee..6c094ee 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 bee060a..f76ff7f 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 6164734..09337e5 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();
+ }
+
}
}
--
cgit v1.1