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') 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') 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') 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') 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